shell_xargs

学的东西虽然还算不少,但是却并没有很好的运用起来,在某些文章的指导下总会有一种豁然开朗的感觉,只想说一句话:我靠,还能这么用,666

题外话:就比如说之前遇到一个删软件的问题,用find找到了许多文件,但是却无法传递给rm,因为它并不能支持读取标准输入,最后是通过写了一个脚本,通过变量的方式来让rm删除的。

但是今天遇到了xargs这个命令,可以将读取到的标准输入作为参数传递给后面的命令,真的六

但是竟然有更简单的方法,第一是find本身就支持-exec来执行操作

还有就是仍然使用变量的方式,但是却是rm $(find ...),我之前也学过shell中这种使用命令的方式,但是竟然没想到这个方法,这也太六了吧。当然了同样的可以这样写

rm `find ...`

我总结的xargs的作用

一句话,太强大了

  1. 最常用的便是读取标准输出作为参数传递给后面的命令

  2. 可以用来做许多格式化输出操作

  3. 不仅可以读取标准输入,还能读取文件,只需要-a参数就可以啦,并不需要标准输入

WHY

之前学过管道命令,觉得这个命令超级好用,但是后来发现了管道命令的弊端,就是很多命令根本就不支持标准输入。

比如我想一次性删除以 .txt 结尾的文件,但是 rm 不支持管道来传参,例如这样写就是错误的

1
ls *.txt | rm

但是有了 xargs 这个命令之后便可以做到了

1
ls *.txt | xargs rm

其实只要 rm *.txt 就可以了,这里只是举个例子


语法格式

1
somecommand |xargs -item  command

应用

1
2
3
4
# cat test.txt
a b c d e f g h i
j k l m n
o p q r s t u v w x y z
多行输入单行输出:
1
2
# cat test.txt | xargs
a b c d e f g h i j k l m n o p q r s t u v w x y z
-n 指定每行的列数:
1
2
3
4
5
6
7
8
9
10
11
# cat test.txt | xargs -n3

a b c
d e f
g h i
j k l
m n o
p q r
s t u
v w x
y z
-d 自定义一个定界符:
1
2
3
# echo "nameXnameXnameXname" | xargs -dX

name name name name
-I 将值保存在{}中,并使用{}取出值:

复制所有图片文件到 /data/images 目录下:

1
ls *.jpg | xargs -n1 -I {} cp {} /data/images

当然了,其实只要使用 cp *.jpg /data/images 即可

-0 将null作为分隔符:

xargs默认是通过空格作为分隔符的,可是当一个文件名中出现了空格,或者是删选有许多空格的命令,那么就不能使用空格作为分隔符了,可以使用-d来指定,但是更好的是使用-0,这个命令就需要配合find命令一起使用

因为find提供了print0这个参数在文件名后输出null,而不是换行符(换行符会被 xargs 替换成空格)。

统计一个源代码目录中所有 php 文件的行数:

1
find . -type f -name "*.php" -print0 | xargs -0 wc -l
-p 交互模式:
1
# cat url-list.txt | xargs -p wget -c
-a 直接读取文件:
1
xargs -a url-list.txt -p wget -c