xargs有什么用?
在linux中,有pipeline的概念,上一个命令执行完后,可以接着下一个命令执行。
比如我上一个命令是ls
# ls cert channel msp msp.bak orderer root-org1.crt
可以通过pipeline管道,接下一个grep命令
# ls|grep order orderer
pipeline把上一个命令的标准输出stdout, 重定向到下一个命令的标准输入std,实现数据的传递。
有的linux命令是可以直接从stdin读取参数的,比如grep。但是有的命令是不可以的,比如ls, rm ,echo等
# ls|echo
执行上述命令,我们会发现什么都没有
为了解决这个问题,让这些命令都能从stdin标准输入读取参数,就是xargs的使命:
# ls|xargs echo cert channel msp msp.bak orderer root-org1.crt
xargs把读取的参数用空格分隔,传递给后续命令。但注意的是,虽然它把参数按空格分离了出来,xargs不是传递一个参数,执行一次命令,而是把这些参数一次性的全部传递给后续命令
比如下面,xargs把空格分割的一整行参数全部传递给了第二个echo
$ echo {0..9}|xargs echo 0 1 2 3 4 5 6 7 8 9
我们希望控制xargs传递参数的个数,比如我们想两个参数一组,传递给echo。就需要-n参数。-n指定传递给xargs后续命令的最多参数个数
# echo {0..9}|xargs -n2 echo 0 1 2 3 4 5 6 7 8 9
其他常见用法
想把所有.jpg文件删除,当然你可以rm *.jpg,但是如果要递归操作所有子目录下的文件呢?
可以这样:
find . -name "*.jpg" | xargs rm
这样,所有被find找到的文件名,都会作为参数来调用rm命令了。
对于大多数情况,这一行命令没有问题,但是如有些文件名中包含空格,就会有问题了。xargs默认以空白符分隔接受到的输入,所以一个含有空格的文件名会被当做多个参数,分别传给rm。所以在处理文件名这类命令时,通常要这样:
find . -name "*.jpg" -print0 | xargs -0 rm
这里的-print0是告诉find命令,在每个输出后面以’\0’作为结束。-0是告诉xargs,使用’\0’来分隔输入,而不是空白符。这样就避免出现问题了。
下面再考虑另一种情况,假设不是删除,而是想把符合要求的文件名都添加上后缀.bak怎么办?这时候需要这样:
find . -name "*.jpg" -print0 | xargs -0 -I {} mv {} {}.bak
其中的-I {}是告诉xargs,后面的命令中,用{}表示占位符,将会被实际的参数替代。这样就行了。
其他有用的参数还有:
* -d 用于指定切分输入内容时,具体的分隔符
其他更多的参数,就参考man xargs吧。
Ref:
- https://blog.csdn.net/yhcharles/article/details/44875865
发表回复