来也匆匆 几十繁华一阵风; 去也匆匆 回头一看已成空
分类: Android平台
2015-09-11 14:06:08
xargs是给命令传递参数的一个过滤器,也是组合多个命令的一个工具.它把一个数据流分割为一些足够小的块,以方便过滤器和命令进行处理.由此 这个命令也是后置引用的一个强有力的替换.在一般使用过多参数的命令替换失败的时候,用xargs来替换它一般都能成功.通常情况下,xargs从管道或 者stdin中读取数据,但是它也能够从文件的输出中读取数据. xargs的默认命令是echo.这意味着通过管道传递给xargs的输入将会包含换行和空白,不过通过xargs的处理,换行和空白将被空格取代.
假设有这样一个需求,我们需要从/home/rain文件系统中搜索字符串hello,命令如下:
$grep -i "hello" /home/rain/*
这将导致命令行参数太多。而每个系统对于参数列表的大小都有限制。比如ARG_MAX一般至少定义为4096 bytes, 如果超过了ARG_MAX,将产生shell错误:
Argument list too long , 为了避免这个问题可以使用xargs命令, 格式为:
xargs [opt] [ command [initial-arguments] ]
其中opt是xargs本身的命令行参数。
它的作用为,build and execute command lines from standard input。他从stdin读取由空格分割的字符串(假设为arg0,arg1,… argN),并执行command [initial-arguments] arg0 arg1 …argN,如果参数太多的话,xargs保证参数大小在不超过系统限制的ARG_MAX bytes大小的前提下,一次或多次执行command [initial-arguments]命令。比如执行了如下命令:
$find / -name ‘*.h’ | xargs grep –i ‘stdin’ | less
假设执行两次,第一次为grep –i ‘stdin’ a1.h a2.h … a3000.h | less
第二次为grep –i ‘stdin’ a3001.h a3002.h … a4000.h | less
该命令的实际执行情况为:(推测)
Shell执行find,xargs和less程序, xargs顺序执行了两次grep程序。
xargs从find的结果读取数据是很普通的,不需要额外的解释。
xargs同less的数据传递看起来有些麻烦,其实也挺简单的。xargs从stdin读取管道的数据,并按照ARG_MAX为界限进行分割,执行fork和execv(“grep”)一次或多次就可以了。因为grep使用普通的printf来输出结果,而这样的结果正好作为less的输入。因为xargs和grep虽然存在父子关系,但是他们的stdout是同一个stdout。对于less程序来讲,grep的输出和xargs的输出是没有区别的。
注意:
[1] XXX | grep –i ‘hello’
[2] XXX | xargs grep –i ‘hello’
[1]的情况下,grep将通过管道读取XXXX的输出结果,并在该结果中搜索hello。
[2]的情况下,xargs将通过管道读取XXXX的输出结果,并将该结果作为grep的最后的FILE参数,和grep –i ‘hello’组合成完整的命令(如 grep –i ‘hello’ stdio.h stdlib.h)后,执行该命令。grep从stdio.h stdlib.h文件中搜索hello。
两者对于管道的输出作不同的处理,前者是grep直接从stdin中读取管道数据,并搜索。后者是xargs(他的命令行选项为 grep –i ‘hello’)直接从stdin中读取管道数据,并和grep –i ‘hello’组合,然后调用exec执行该命令。这种不同是体现在grep和xargs对读取管道数据后采取的不同处理,和管道本身的机制没有关系。