18 xargs (从新手到菜鸟的Linux教程)

接上篇,那么怎么把标准输出的内容作为命令参数呢?光用管道符可不行啊,因此我们还需要 xargs 帮忙。

照例先贴 man xargs

XARGS(1) General Commands Manual

NAME xargs - build and execute command lines from standard input

SYNOPSIS …

DESCRIPTION This manual page documents the GNU version of xargs. xargs reads items from the standard input, delimited by blanks (which can be protected with double or single quotes or a backslash) or newlines, and executes the command (default is /bin/echo) one or more times with any initial-arguments followed by items read from standard input. Blank lines on the standard input are ignored.

那么看起来 xargs 可以把标准输入的内容和指定的命令程序名拼接起来,生成一个‘命令 参数’的模式。

我感觉还是举个例子比较形象。

$ echo "some content of file1" > file1
$ ls
file1
$ ls | xargs cat
some content of file1

还是解释一下吧= = ls 把当前目录下的文件列表列了出来,在管道符的作用下传给了 xargs cat,然后 xargs 将标准输入的内容 file1 和自己本来的参数 cat 拼在一起得到命令 cat file1 。OK?

但是如果文件名有空格就有点小麻烦咯……

$ test echo "wa, space in file name can cause some small problems" > 'file 2'
$ test ls
 file1  'file 2'
$ test ls | xargs cat
some content of file1
cat: file: No such file or directory
cat: 2: No such file or directory

这是为啥呢?我们再来仔细读读 man xargs

Because Unix filenames can contain blanks and newlines, this default behaviour is often problematic; filenames containing blanks and/or newlines are incorrectly processed by xargs. In these situations it is better to use the -0 option, which prevents such problems. When using this option you will need to ensure that the program which produces the input for xargs also uses a null character as a separator. If that program is GNU find for example, the -print0 option does this for you.

哦?看来如果想要防止空格被误认为是分隔符,只要开启 -0 选项就行(当然管道前的命令也要将 \0 作为分隔符才行)。我们来看看手册给出的例子

$ find . -name 'file*' -print | xargs cat   
cat: ./file: No such file or directory
cat: 2: No such file or directory
some content of file1
$ find . -name 'file*' -print0 | xargs -0 cat 
wa, space in file name can cause some small problems
some content of file1
$ find . -name 'file*' -print0 | xargs -0 echo
./file 2 ./file1

也就是说通过 find . -name 'FILE_PATTERN' -print0 查找并打印文件名的时候是以 \0 作为分隔符的,配合 xargs -0 COMMAND 食用 口味更佳

xargs 其他的用途暂时没想到……想起来再来更新好了。