1.为什么使用xargs
Linux中的管道我们都比较熟悉,我日常经常使用 ps -ef | grep xxx 这种方式查找线程。
管道实现的是将前面的输出部分转换为后面的输入。但是在我们日常使用脚本开发的时候希望管道传递过来的是参数,但是直接使用管道有时无法传递到命令的参数位
如下面的例子,如果不使用xagrs,则不会将前面的输出部分传到正确的位置,导致ls直接输出文件夹下所有的内容,如个加上xagrs,则会将前面的输出正确地传输到后面的具体的参数位置
[root@67 ldj]# find / -name kkk | xargs ls -l
-rw-r--r-- 1 root root 77 Mar 17 16:45 /ldj/kkk
[root@67 ldj]# find / -name kkk | ls -l
total 8
drwxr-xr-x 3 root root 15 Mar 17 15:47 1
-rw-r--r-- 1 root root 77 Mar 17 16:45 kkk
-rw-r--r-- 1 root root 8 Mar 18 14:40 test
[root@67 ldj]# ll
drwxr-xr-x 3 root root 15 Mar 17 15:47 1
-rw-r--r-- 1 root root 77 Mar 17 16:45 kkk
-rw-r--r-- 1 root root 8 Mar 18 14:40 test
还有一点是我们在kill线程的时候,我们常规的方法一般如下
root@67 ~]# kill `ps -ef | grep 'Elasticsearch'`
-bash: kill: root: arguments must be process or job IDs
-bash: kill: (51704) - No such process
-bash: kill: (51701) - No such process
-bash: kill: 15:35: arguments must be process or job IDs
......
以及循环的这种方式,其实和第一种差不多都是 kill $pid
for procid in $(ps -aux | grep "Elasticsearch" | awk '{print $2}'); do kill -9 $procid; done
但是我们如果使用xargs,直接将前面的输出内容转换为后面的参数
ps -ef | grep ''Elasticsearch'' | xargs kill
2.xagrs的使用
我们在使用之前需要了解的是,使用xargs先会对管道之前的输出数据进行分割,在分批处理,然后传输到正确的参数位置。
2.1一些常用的选项
- -d选项
-d选项是分隔符,默认分割符是空白分割,并且分隔符只能是单个字符,不能以\开头
[root@67 ~]# echo "aabbcc" | xargs -d 'b' echo
aa cc
[root@67 ~]# echo "aabbcc" | xargs -d 'b' echo |grep -e " "
aa cc
[root@67 ~]# echo "aabbcc" | xargs echo
aabbcc
[root@67 ~]# echo "aabbcc" | xargs -d 'bb' echo
xargs: Invalid input delimiter specification bb: the delimiter must be either a single character or an escape sequence starting with \.
- -n选项
-n选项表名将xargs生成的命令参数,传递给多少个参数给后面的命令执行
[root@67 ~]# echo "00a11a22a33a44a55a66a77a88a99a" | xargs -d 'a' -n 4 echo
00 11 22 33
44 55 66 77
88 99
[root@67 ~]# echo "00a11a22a33a44a55a66a77a88a99a" | xargs -d 'a' -n 5 echo
00 11 22 33 44
55 66 77 88 99
- -p选项
使用该选项,会使命令暂停,如果输入y则会输出结果,否则不执行
[root@67 ~]# echo "a#b#c" | xargs -p -d '#' echo
echo a b c
?...y
a b c
- -E选项
将-E后面指定的字符串之前的内容传递给后面的命令,不能够和-d一起使用,否则失效
[root@67 ~]# echo "a#b#c" | xargs -d '#' | xargs -E 'b' echo
a
[root@67 ~]# echo "a#b#c" | xargs -d '#' | -E 'b' echo
a b c
- -i选项
-i或是-I:linux支持类型不同,将xargs的每项名称,一般是一行一行赋值给{},可以用{}代替。选项告诉 xargs 可以使用{}代替传递过来的参数。主要作用是当xargs command 后有多个参数时,调整参数位置
-i:默认替换字符为{}、-I:指定替换字符,一般为{}、可替换成$ @等符号、一般是{}。建议使用-I,其符合POSIX标准
[root@67 ~]# echo "a#b#c" | xargs -i echo {}
a#b#c
[root@67 ~]# echo "a#b#c" | xargs -I @ echo @
a#b#c
root@hdfa67 txt]# find /root/txt -name "*.txt"
/root/txt/2.txt
/root/txt/3.txt
/root/txt/1.txt
[root@67 txt]# find /root/txt -name "*.txt" -print0
/root/txt/2.txt/root/txt/3.txt/root/txt/1.txt
xargs的 -0 和 分隔符 “\0”实际上左右是一样的
[root@67 txt]# find /root/txt -name "*.txt" -print0 |xargs -0 echo
/root/txt/2.txt /root/txt/3.txt /root/txt/1.txt
[root@67 txt]# find /root/txt -name "*.txt" -print0 |xargs -d '\0' echo
/root/txt/2.txt /root/txt/3.txt /root/txt/1.txt
如果不加-print0实际上,会将结果直接换行,但是由于换行符也是xargs的默认空白符一种,因此下面的命令也是可以得到结果的
[root@67 txt]# find /root/txt -name "*.txt" |xargs echo
/root/txt/2.txt /root/txt/3.txt /root/txt/1.txt
[root@67 txt]# find /root/txt -name "*.txt"
/root/txt/2.txt
/root/txt/3.txt
/root/txt/1.txt