概述
xargs指令可以从标准输入读取数据,并利用这些数据“组建”并“执行”指令。它的作用是将参数列表转换成小块分段传递给其他命令,以避免参数列表过长的问题。
语法
xargs [-0prtx] [-E eof-str] [-e[eof-str]] [--eof[=eof-str]] [--null]
[-d delimiter] [--delimiter delimiter] [-I replace-str]
[-i[replace-str]] [--replace[=replace-str]] [-l[max-lines]]
[-L max-lines] [--max-lines[=max-lines]] [-n max-args]
[--max-args=max-args] [-s max-chars]
[--max-chars=maxchars] [-P max-procs] [--max-procs=max-procs]
[--process-slot-var=name] [--interactive] [--verbose] [--exit]
[--no-run-if-empty] [--arg-file=file] [--show-limits] [--version]
[--help] [command [initial-arguments]]
详解
xargs 从标准输入中读取使用“空格”或“空行”分隔的“数据块”,并以读入的“数据块”作为参数执行命令(默认情况下执行的是 /bin/echo
命令)。需要注意的是,作为参数,从标准输入中读入的“数据块”会跟随在 初始参数(initial-arguments)之后。如果你从标准输入读入的“数据块”中有些空格并非“数据块”的分隔,而是作为“数据块”的一部分出现;你需要把这个带有空格的“数据块”整体放到单引号或双引号中,当然你也可以在那些“数据块”内部的空格前用反斜杠()进行转义。另外,标准输入中多余的空行会被忽略。
如果不使用 -n
和 -L
选项,并且没有遇到换行符的情况下,被 xargs 创建的命令的长度是“贪婪”的,直到达到系统限制的长度。而 Command 指令被调用的次数正好是标准输入中“数据块”的行数。通常情况下,命令被调用的次数是小于“数据块”的数量的;这样会在一定程度上提高命令的执行效率。有些指令可以并行执行,请参考 -P 选项。
在 Unix 系统中,文件名中是可以包含空格和换行符的,如果不对这种“特殊情况”做处理通常是会出问题的;这种在文件名中的空格和换行会被 xargs 当成“数据块”的分隔符处理。在这种情况下可以使用 -0 选项来解决问题。当使用这个-0选项时,你需要确保“数据块”之间使用null字符作为分隔符。例如:当由GNU 的 find 命令提供xargs的“标准输”时,就需要为其(find)提供 -print0 选项来达到目的。
如果有任何一次 Command 指令的调用以 255 的状态码退出,则xargs会立即停止,并会放弃此后的所有输入。错误信息会输出到“标准错误流”。
参数说明
- -0, --null:当 xargs 使用此选项时,null字符会被作为“数据块”的分隔符,而引号(单引用和双引号)都不在具有特殊含义(所有的字符都代表他们自己);文件结束符(EOF)也将失效。通常情况下,当“数据块”中包含空格、引号、反斜杠时适合使用此选项,GNU 中的
find
命令 使用-print0
选项时就是这种情况。 - -a file, --arg-file=file:从文件中读取“数据块”,而非标准输入。如果你使用此选项,除非“标准输入”已经被重定向到
/dev/null
,否则,执行命令时不会影响“标准输入”中的数据。 - –delimiter=delim, -d delim:xargs 命令会以此选项指定的“特定字符”作为“数据块”的分隔符。这个“特定字符”可能是一个“普通字符”,也可能是一个C语言风格的转义字符(如:\n,反斜杠后进一个十六进制或八进制数的转义字符);这些转义字符会被 printf 函数处理后再给此选项使用。此选项不支持多字节字符(也即是仅支持ASCII字符集中的字符)。使用此选项后,标准输入中的引号和反斜杠都不再是特殊字符,他们仅代表自身的字面意思。另,
-d
选项还会使 文件结束符(EOF)失效,此时xargs 对待文件结束符与其他参数是完全一样的。当“数据块”中包含换行符时你也可以使用此选项来处理;虽然使用--null
选项是更好的选择。 - -E eof-str:设置“文件结束符”,xargs 在处理标准输入时,如果遇到“文件结束符”,则其后的所有输入都将被忽略。如果
-E
和-e
选项都没有被使用,则表示在标准输入中没有字符会被当成“文件结束符”处理。 - -e [eof-str], --eof[=eof-str]:此选项和
-E
选项的功能是一样一样的。请使用 -E 选项,因为他是符合 POSIX 标准的,而此选项不是。如果使用此选项时eof-str
被省略了或-E
和-e
选项都没有被使用,则表示在标准输入中没有字符会被当成“文件结束符”处理。 - -I replace-str:用从标准输入中得到“数据块”替换
initial-arguments
中出现的replace-str
。使用此选项后,空格(无论是否在引号中)不会作为“数据块”的分隔符,只有换行会被作为“数据块”的分隔符。使用此选项,同时意味着使用了-x
和-L 1
选项。 - -i [replace-str], --replace[=replace-str]:此选项与
-I
选项的功能是一样的。如果replace-str
没有被指定,则使用默认值{}
,此时的功能与-I {}
是一样的。这个选项已经不推荐使用,请使用 -I 选项。 - -L max-lines:每个命令行最多允许有
max-lines
个非空的输入行。末尾的空白会使一个输入行在逻辑上延伸到下一行。使用此选项,同时意味着使用了-x
选项。 - -l [max-lines], --max-lines[=max-lines]:此选项和
-L
选项的功能是一样的;不同的是此选项中的 max-lines 参数是可选的。如果max-lines
没有被指定,则使用默认值 1 。此选项-l
不已经不赞成被使用,请使用符合 POSIX 标准的-L
选项代替。 - -n max-args, --max-args=max-args:每个命令最多允许有
max-args
个参数。如果参数个数达不到max-args
个,但参数的尺寸超过了限制(请参考-s
选项);此是 xargs 程序将会退出。 - -P max-procs, --max-procs=max-procs:同时运行
max-procs
个进程,max-procs
的默认值是1。如果max-procs
被指定为0,xargs 将会尽可能的运行多个进程。请联同-n
或-L
选项一起使用,否则可能只会执行一个进程。在 xargs 运行期间,你可以向他发送SIGUSR1
信号量要求增加进程,或发送SIGUSR2
信号量要求减少进程。但是你无法把进程数据减少到0,因为最小值是1。xargs 不会中止命令的执行,当要求减少进程时,他会等待,只到有进程执行完成,只是在执行完成的进程想要启动其他进程时会被阻止。 - -p, --interactive:交互式的运行命令,每个命令运行前都会在终端询问用户是否要执行。只有在用户响应询问时输入
y
或Y
时才会去运行命令。打开此选项的同时,意味着-t
选项也被打开了。 - –process-slot-var=name:在每个子进程中分别设置环境变量
name
的值为不同的值。如果在某个进程中设置的值与已经存在的进程设置的值重复了,就会退出这个进程。可以用此来做负载均衡。 - -r, --no-run-if-empty:如果标准输入中没有任何非空的字符,则不运行命令;默认情况下即使标准输入没有非空字符,命令也会被运行一次。这个选项是 GNU 扩展的。
- -s max-chars, --max-chars=max-chars:一个命令最多包含
max-chars
个字符,包括 命令本身、initial-arguments
和标识字符结束的 nulls 字符。这个最大值是依赖于操作系统的。 - -t, --verbose:在执行命令之前输出此命令的“标准错误流”。
- -x, --exit:如果超过
-s
选项指定尺寸,就退出程序。请参考-s
选项。
xargs命令用法
xargs用作替换工具,读取输入数据重新格式化后输出。
定义一个测试文件,内有多行文本数据:
[root@peipei3514 logs]# 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
多行输入单行输出
[root@peipei3514 logs]# 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
选项多行输出
[root@peipei3514 logs]# cat test.txt | xargs -n 3
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
[root@peipei3514 logs]# cat test.txt | xargs -n 5
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
选项可以自定义一个定界符
[root@peipei3514 logs]# echo "nameXnameXnameXname" | xargs -d X
name name name name
结合-n选项使用
[root@peipei3514 logs]# echo "nameXnameXnameXname" | xargs -dX -n2
name name
name name
读取stdin,将格式化后的参数传递给命令
假设一个命令为 sk.sh 和一个保存参数的文件arg.txt:
[root@peipei3514 logs]# vim sk.sh
#!/bin/bash
#sk.sh命令内容,打印出所有参数。
echo $*
arg.txt文件内容:
[root@peipei3514 logs]# vim arg.txt
aaa
bbb
ccc
xargs的一个选项-I
,使用-I
指定一个替换字符串{}
,这个字符串在xargs扩展时会被替换掉,当-I
与xargs
结合使用,每一个参数命令都会被执行一次:
[root@peipei3514 logs]# cat arg.txt | xargs -I {} ./sk.sh -p {} -l
-p aaa -l
-p bbb -l
-p ccc -l
复制所有图片文件到 /data/images 目录下
ls *.jpg | xargs -n1 -I cp {} /data/images
xargs结合find使用
用rm 删除太多的文件时候,可能得到一个错误信息:/bin/rm Argument list too long. 用xargs去避免这个问题:
find . -type f -name "*.log" -print0 | xargs -0 rm -f
xargs -0将\0作为定界符。
统计一个源代码目录中所有php文件的行数
find . -type f -name "*.php" -print0 | xargs -0 wc -l
查找所有的jpg 文件,并且压缩它们
find . -type f -name "*.jpg" -print | xargs tar -czvf images.tar.gz
xargs其他应用
假如你有一个文件包含了很多你希望下载的URL,你能够使用xargs下载所有链接:
cat url-list.txt | xargs wget -c
子Shell(Subshells)
运行一个shell脚本时会启动另一个命令解释器.,就好像你的命令是在命令行提示下被解释的一样,类似于批处理文件里的一系列命令。每个shell脚本有效地运行在父shell(parent shell)的一个子进程里。这个父shell是指在一个控制终端或在一个xterm窗口中给你命令指示符的进程。
cmd1 | ( cmd2; cmd3; cmd4 ) | cmd5
如果cmd2 是cd /
,那么就会改变子Shell的工作目录,这种改变只是局限于子shell内部,cmd5则完全不知道工作目录发生的变化。子shell是嵌在圆括号()内部的命令序列,子Shell内部定义的变量为局部变量。
子shell可用于为一组命令设定临时的环境变量:
COMMAND1
COMMAND2
COMMAND3
(
IFS=:
PATH=/bin
unset TERMINFO
set -C
shift 5
COMMAND4
COMMAND5
exit 3 # 只是从子shell退出。
)
# 父shell不受影响,变量值没有更改。
COMMAND6
COMMAND7