Get argument from pipe

前端 未结 3 2280
清酒与你
清酒与你 2021-02-20 04:28

Consider having the results from the pipe:

find .

Now I would like to access in the second command behind the pipe what is actually piped (inpu

3条回答
  •  一整个雨季
    2021-02-20 05:13

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

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

    (The -r is for 'raw' input; it stops the shell expanding backslash escape sequences in the input, and is a standard POSIX feature of the read command in the shell.)

    Since you mention bash, you can avoid problems with newlines in the file names by using the find . -print0 option to terminate each name by a null byte ('\0' in C) instead of a newline, and then use:

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

    The -d '' replaces the normal newline delimiter with the first character of the string argument, but the string is empty so the first character is the only character is a null byte.

    There isn't an easy way (nor, as far as I know, a hard way) to use a for loop along the lines of:

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

    which works reliably for names with spaces, or newlines in them.

    Often, you may want to use the xargs command. This reads standard input and creates a command line using what's read from standard input as arguments to the command.

    find . | xargs wc -l
    

    Or, with newline and space safety (by default, xargs splits arguments at spaces, tabs and newlines):

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

    There are a lot of options you can apply to xargs — especially the GNU version.

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

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

    which does basically the same job as the find . -print0 | xargs -0 wc -l command. One difference is that if there are no files in the output from find, then using -exec won't execute wc at all, whereas by default, xargs will execute it once (with no file name argument; this is for POSIX compliance). With GNU xargs, you can use -r or --no-run-if-empty to stop that happening. Mac OS X xargs seems to do that anyway.

提交回复
热议问题