Get argument from channel

Consider the results from the pipe:

find . 

Now I would like to access the second command behind the pipe, which is actually connected to the channel (entered), and then, for example, to print twice.

 find . | printf $arg$arg\n #each filename would be printed twice per line 

Please note that the question does not ask to print everything that once gets from the channel twice, I know how to use the bash loop for or write a script that could execute the one mentioned. How can I get $ arg to use it quickly in embedded scripts?

$ 0 and $ 1 do not work as in script files.

+4
source share
3 answers

Short answer: You can print each file twice with sed:

 find . | sed 's/.*/& &/' 

Sed can edit lines as they are entered. The above command says s (substitute) .* (Entire line) & & (with itself, twice).

Longer answer:. When you connect one program to another, you connect the first standard program output stream to the second standardized program stream. Everything that the first program prints will be considered as input for the second program.

Unfortunately, for your example, input is not included in string strings that map well with the hypothetical variable $args . It comes in a large monolithic stream. If you want to print each line of the stream twice, you can use sed (which is the Stream Editor), but it just does the replacement in turn.

+5
source

Ignoring the possibility that file names contain newlines, you can use sed as pringley in your answer, or you can create a while with the read command:

 find . | while read -r line do echo "$line$line" done 

( -r is for raw input, it stops the shell extending backslash escape sequences in the input, and is a standard POSIX function of the read command in the shell.)

Since you mention bash , you can avoid problems with new characters in file names using the find . -print0 parameter find . -print0 find . -print0 to complete each name with a null byte ( '\0' in C) instead of a new line, and then use

 find . -print0 | while read -r -d '' line do echo "X${line}${line}X" done 

-d '' replaces the normal newline separator with the first character of the string argument, but the string is empty, so the first character is the only character - zero byte.

There is no easy way (and as far as I know it’s hard) to use a for loop line by line:

 for line in $(find .) do echo "X${line}${line}X" done 

which works reliably for names with spaces or newlines.

Often you can use the xargs command. This reads standard input and creates a command line using read from standard input as command arguments.

 find . | xargs wc -l 

Or with newline and space security (by default, xargs separates arguments in spaces, tabs, and newline characters):

 find . -type f -print0 | xargs -0 wc -l 

There are many options you can apply to xargs - especially the GNU version.

However, you also have find options that basically make xargs redundant:

 find . -type f -exec wc -l {} + 

which does basically the same job as the find . -print0 | xargs -0 wc -l find . -print0 | xargs -0 wc -l find . -print0 | xargs -0 wc -l . One of the differences is that if there are no files on the output from find , then using -exec will not execute wc , while by default xargs will execute it once (without a file name argument; this is for POSIX compliance). With GNU xargs you can use -r or --no-run-if-empty to stop this. Mac OS X xargs doesn't seem to care.

+6
source
 find . | xargs -I{} printf "%s%s\n" {} {} 
+3
source

Source: https://habr.com/ru/post/1493330/


All Articles