xDroid's Blog

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 其他的用途暂时没想到……想起来再来更新好了。