命令 xargs 有点复杂,最主要的是因为这个命令没法单独使用,它一般与其它命令配合使用,因为其它命令对输入的要求不同,所以会给大家造成困惑。

命令 xargs 的参数非常多,我们通过例子来理解xargs的工作机制,及以各种参数的应用场景。
xargs命令的格式如下
xargs [-options] [command]
xargs 的功能是将标准输入与它后面接的其它命令拼成完整的命令行,然后执行拼接的命令行。我们通过--verbose参数来看xargs实际的执行命令:

xargs 接受的是标准输入,在Linux系统中所有对象都是文件,标准输入的文件标识符是0,标准输出文件标识符是1,标准错误文件标识符是2。管道的作用是将上一个命令的标准输出作为下一个命令的标准输入。
bash$ touch a b cbash$ lsa b cbash$ ls | xargs --verbose echoecho a b ca b c
上面的例子我们可以分步执行,看看它们的输入输出都是什么。首先ls的输出是当前目录中的文件,我们把 ls 的标准输出重定向,看下输出文件的内容。

Linux下的重定向符号 < > ,两个符号分别代表标准输入重定向和标准输出重定向。
< 等价于 0<
> 等价于 1>
我们查看到 ls 的输出实际上是以换行符分隔的,a b c 三个文件每个一行。下面我们分解执行xargs,刚才说了xargs的输入是标准输入,并不是一定要配合管道来执行,我们把 ls 重定向的文件作为 xargs的输入看下执行的结果、

加上 --verbose 选项,xargs会把要执行的命令打在屏幕上。我们发现换行符被xargs 处理掉了,xargs的默认行为会将输入文件中的换行、多余的空格都过滤掉,剩下的内容以空格进行分隔,然后转给它接的命令。这里演示的命令是echo,我们再演示一下 rm ,删文件

为了深入理解xargs的作用,我们把输入文件人为地修改一下,在vim下使用 : set list,让换行符和空格可见,我们在输入文件中加入一些空行和空格。

编辑完后,cat 查看一下效果

这里原始文件已经被加入了一些空格和换行,我们重新执行 xargs 看下它是否还会去除掉多余的换行和空格。

到这儿,我们基本搞清楚了 xargs 的工作机制。我们文章标题中说 xargs 是自带循环的命令,这个如何理解?xargs 除了可以将输入内容整个拼成一个字符串,它还支持循环执行。
到这儿要介绍它的另一个参数 -n , 我们通过例子来理解
bash$ touch a b cbash$ ls | xargs --verbose -n 1 rmrm arm brm c
这个例子中,每一个字段都被拆成了一个命令行参数与 rm 拼结。相当于循环执行了三遍 rm ,其中 -n 后面的数字决定了几个字段一组,-n 1 就相当于ls列出的文件,每一行都执行一个rm。我们知道很多命令行的参数有长度限制。xargs 的默认行为是把所有的输出整成一个命令行,如果接 rm ,有时命令行过长就会报错。多行循环执行除了解决参数过长的问题,还可以提高并发。当然如果要并发执行,还需要加 -P 参数,后面接数字,表示同时可以执行几个。这里我们留个问题,并发执行是等一组任务都执行完了再执行下一组,还是随时补充新的任务,维持参数指定的并发数。
有了 -n , -P,很多读取列表循环执行的程序都不用写了,xargs就是一个循环。下面的例子,一次并发执行两个删除:

效果不明显,我们构造一个需要一些时间才能执行完成的程序,看下并发下的情况。
先构造一个随机休眠的脚本testloop.sh :

每次执行两个任务,我们看一下效果

从执行情况来看,-P 2 保障最大并发进程为2,当其中一个执行完成,它会立即启动下一个任务,并保障最大并发为2。




