eXtended ARGuments
xargs命令的作用,是将标准输入转为命令行参数。
结合管道,它能把一个命令的输出,变为另外一个命令的参数。
一、参数与标准输入
命令都带有参数,有些命令可以接受"标准输入"(stdin)作为参数。
参数:ls test.txt
标准输入:cat /etc/passwd | grep root
怎么分辨一个命令可不可以接收标准输入?
很简单,当你敲完命令回车后,终端会等待接收你的输入,例如当你在终端输入cat后,终端会等待你输入字符,当你输入一些字符后,然后按Ctrl-d发送终止符号。这时cat命令接收标准输入完毕,执行命令,也就是将刚才键入的内容输出的标准输出上(屏幕)。
之所以有xargs这个命令,是因为大多数命令都不接受标准输入作为参数,这导致无法用管道命令传递参数。
find /sbin -perm +700 |ls -l #这个命令是错误的
find /sbin -perm +700 |xargs ls -l #这样才是正确的
xargs 一般是和管道一起使用。
二、命令格式:
command1 | xargs [options] command2
三、选项:
- -a file 从文件中读入作为 stdin
- -e flag ,注意有的时候可能会是-E,flag必须是一个以空格分隔的标志,当xargs分析到含有flag这个标志的时候就停止。
- -p 当每次执行一个argument的时候询问一次用户。
- -n num 后面加次数,表示命令在执行的时候一次用的argument的个数,默认是用所有的。
- -t 表示先打印命令,然后再执行。
- -i 或者是-I,将参数赋值给 {},可以用 {} 代替。
- -r no-run-if-empty 当xargs的输入为空的时候则停止xargs,不用再去执行了。
- -s num 命令行的最大字符数,指的是 xargs 后面那个命令的最大命令行字符数。
- -L num 从标准输入一次读取 num 行送给 command 命令。
- -l 同 -L。
- -d delim 分隔符,默认的xargs分隔符是空白
- -x exit的意思,主要是配合-s使用。。
- -P, --max-procs=MAX-PROCS 同时运行至多<MAX-PROCS>个进程
四、基本用法
1.单独使用
xargs后面的命令默认是echo。
xargs # 等同于 xargs echo
大多数时候,xargs命令都是跟管道一起使用的。但是,它也可以单独使用。
输入xargs按下回车以后,命令行就会等待用户输入,作为标准输入。你可以输入任意内容,然后按下Ctrl d,表示输入结束,这时echo命令就会把前面的输入打印出来
xargs hello (Ctrl + d)
hello
再看一个例子
xargs find -name "*.txt"
./foo.txt ./hello.txt
上面的例子输入xargs find -name以后,命令行会等待用户输入所要搜索的文件。用户输入"*.txt",表示搜索当前目录下的所有 TXT 文件,然后按下Ctrl d,表示输入结束。这时就相当执行find -name *.txt
2.-0与find
由于xargs默认以空白(包括空格、Tab、换行)作为分隔符,所以不太适合处理文件名,因为文件名可能包含空格。
find命令有一个特别的选项-print0,表示find输出的每条结果后面加上 '\0' 也就是null,而不是换行。
xargs命令的-0选项表示用null当作分隔符。
find /path -type f -print0 | xargs -0 rm
上面命令删除/path路径下的所有文件。由于分隔符是null,所以处理包含空格的文件名,也不会报错。
xargs 的-0选项不仅可以将分隔符从默认的空格变成 NULL,还会将单引号、双引号、反斜线等统统默认为是普通字符。所以说,-0选项特别适合处理命令参数中含有引号、空格、反斜线的情况。
还有一个原因,使得xargs特别适合find命令。有些命令(比如rm)一旦参数过多会报错"参数列表过长",而无法执行,改用xargs就没有这个问题,因为它对每个参数执行一次命令。
$ find . -name "*.txt" -print0 | xargs -0 grep -l "abc"
上面命令找出所有 TXT 文件以后,对每个文件搜索一次是否包含字符串abc。
sudo find / -name '*.*' -type f -print0 | xargs -0 sudo grep -l 'alias ll='
查找包含特定内容的文件
3.-i
-i arg的意思是用arg代替每个参数
ls *.jpg | xargs -n1 -i arg cp arg /data/images
复制所有图片文件到 /data/images 目录下
4.-t
先打印命令再执行命令
ls | xargs -t -i arg echo arg
会打印echo命令,然后再执行的 echo 命令
5.-d
默认情况下xargs以空白(包括空格、Tab、回车换行等)对输入流进行分割,我们可以使用 -d 命令指定分隔符,例如:
echo '11@22@33' | xargs echo
输出:
11@22@33
默认情况下以空白分割,那么11@22@33这个字符串中没有空白,所以实际上等价于 echo 11@22@33 其中字符串 '11@22@33' 被当作echo命令的一个命令行参数
echo '11@22@33' | xargs -d '@' echo
输出:
11 22 33
指定以@符号分割参数,所以等价于 echo 11 22 33 相当于给echo传递了3个参数,分别是11、22、33
-0 和 -d '\0' 是等价的。
6.-p
执行命令时提示,我们可以输入 y 或者 n 来选择是否要执行当前命令:
[roc@roclinux ~]$ find . -type f |xargs -p rm -f
rm -f ./china.txt ./usa.txt ./japan.txt ?...n
上面的命令中,我们输入了“n”,也就是不希望删除这三个文件。
6.-n
-n 3 表示一次传递给xargs后面的命令是3个参数
echo '11@22@33@44@55@66@77@88@99@00' | xargs -d '@' -n 3 echo
输出结果:
11 22 33
44 55 66
77 88 99
00
等价于:
echo 11 22 33
echo 44 55 66
echo 77 88 99
echo 00
实际上运行了4次,每次传递3个参数,最后还剩一个,就直接传递一个参数。
7.-E 选项
-E arg 表示当传递的参数是arg时命令结束。
echo '11 22 33' | xargs -E '33' echo
输出:
11 22
8.-P,--max-procs
xargs默认只用一个进程执行命令。如果命令要执行多次,必须等上一次执行完,才能执行下一次。
--max-procs选项指定同时用多少个进程并行执行命令。
--max-procs 2表示同时最多使用两个进程,
--max-procs 0表示不限制进程数。
docker ps -q | xargs -n 1 --max-procs 0 docker kill
上面命令表示,同时关闭尽可能多的 Docker 容器,这样运行速度会快很多。
9.配合grep
Altitest.py python.py runora.py test.py TransferFile.p
存在以上文件
find . -name '*.py' |grep test
./Altitest.py
./test.py
将前面命令的标准输出作为标准输入传给了grep test,搜索的是文件名列表
find . -name '*.py' -print0 |xargs -0 grep test
./runora.py:testConn = cx_Oracle.connect('user/passwd@tns')
./runora.py:testCursor = testConn.cursor()
./runora.py:testCursor.execute("select * from table")
./runora.py:rows = testCursor.fetchall()
./runora.py:testCursor.close()
./runora.py:testConn.close()
将前面命令的标准输出作为参数传给了grep test,搜索的是文件内容