0x00 xargs默认只能进行简单逻辑
xargs是linux中的常用命令.用来将输入内容放到新的命令中作为参数来运行,在运维中会经常用到这个命令. 实际上xargs和find是同一个包里面的命令,如果去看它们的源代码,会发现find和xargs共用了大量的C代码. 这也是为什么find的-exec选项和xargs命令中默认都会用到{}这个占位符.
xargs命令的常用格式如下,将前一个命令的输出一行一行作为输入参数给到下一个命令
#cat aa |xargs -i echo {} 11 22 33 44
其中-i表示用{}作为输入的占位符放到要执行的命令中. 上面的命令和下面的4条命令等价
echo 11 echo 22 echo 33 echo 44
0x01 怎么在xargs中执行复杂逻辑
默认情况下,xargs中是无法执行复杂逻辑的,也就是说,xargs的后面必须跟上一个命令,xargs只能向这个命令输入参数.
比如我想执行下面的逻辑,对输入的每个参数,都是先echo一下,然后统计行数,我想得到的结果是输出4次1,但是直接报错了,因为xargs会把后面的第一个参数作为一个命令来执行了.当然,是不存在 echo {} | wc -l这个命令的
#cat aa|xargs -i 'echo {} | wc -l' xargs: echo {} | wc -l: No such file or directory
或许大家会想不使用引号是不是就可以了,比如这样,会发现输出为4
#cat aa|xargs -i echo {} | wc -l 4
当我们加上xargs的-t参数,在命令执行之前,在标准错误里面输出要执行的命令,就知道过程了.原来是4条echo命令都执行完成之后,得到的所有输出一起进入到后面的wc命令了
#cat aa|xargs -t -i echo {} | wc -l echo 11 echo 22 echo 33 echo 44 4
有两个方法解决这个问题
1.将要进行的复杂逻辑写入一个脚本中,xargs给脚本输入参数. 这个方法可行,我们写了如下脚本,把需要进行的逻辑写好,$1表示脚本输入参数
#cat mywc #!/bin/bash echo $1 | wc -l
然后进行调用,能看到符合预期. 但是这种情况把整个输入参数都在脚本里面用for处理就可以了,单独写个脚本确实比较麻烦.
#cat aa|xargs -i ./mywc {} 1 1 1 1
2.既然xargs后面必须是一个命令,而且我们可以用脚本来处理复杂逻辑,那么我们就用bash -c来负责复杂逻辑处理,bash -c的效果相当于把-c后面的参数写到一个文件中,然后用bash来执行.
如下的命令和上面单独写脚本的效果.
#cat aa|xargs -i bash -c 'echo {}|wc -l' 1 1 1 1
这儿只列举了在bash -c里面执行两条命令的情况,实际上里面可以写更复杂的逻辑.
0xff 总结
xargs是一个很好用的工具,但是其限制了只能用简单命令,当需要执行复杂逻辑时,我们需要bash这种可以解析详细命令的工具来扩展一下.类似的,我们可以使用python -c来执行一些特殊的解析工作.