xargs命令
大多数 Linux 命令都会产生输出:文件列表、字符串列表等。但如果要使用其他某个命令并将前一个命令的输出作为参数该怎么办
格式:$command | xargs
xargs命令可以将多行输入转换成单行输出
$cat example.txt
1 2 3 4 5 6
7 8 9 10
11 12
$cat example.txt | xargs
1 2 3 4 5 6 7 8 9 10 11 12
xargs也可以分成多行输出,每行输出n个。如:
$cat example.txt | xargs –n 3
1 2 3
4 5 6
7 8 9
10 11 12
xargs可以读取stdin,然后将格式化参数传递给命令,如:
$cat example.txt | xargs –n 7 echo
1 2 3 4 5 6 7
8 9 10 11 12
同时可以结合find使用xargs,如:
$ find . –type f –name “*.txt” –print | xargs rm –f
以上删除文件的做法比较危险,很多文件都可能会包含空格符,而xargs很可能会误认为它们是定界符,一下是较安全的方法:
$ find . –type f –name “*.txt” –print0 | xargs -0 rm –f
xargs -0将\0作为输入定界符。
以下是xargs更强大的一个应用,比如统计所有c程序文件的行数:
$ find . –type f –name “*.c” –print0 | xargs -0 wc -l
例如,file 命令显示文件类型(可执行文件、ascii 文本等);您可以处理输出,使其仅显示文件名,现在您希望将这些名称传递给 ls -l 命令以查看时间戳记。xargs 命令就是用来完成此项工作的。它允许您对输出执行其他某些命令。记住下面这个来自于第 1 部分中的语法:
file -Lz * | grep ASCII | cut -d":" -f1 | xargs ls -ltr
让我们来剖析这个命令字符串。
第一个,file -Lz *,用于查找是符号链接或者经过压缩的文件。它将输出传递给下一个命令 grep ASCII,该命令在其中搜索 "ASCII" 字符串并产生如下所示的输出: alert_DBA102.log: ASCII English text
alert_DBA102.log.Z: ASCII text (compress'd data 16 bits)
dba102_asmb_12307.trc.Z: ASCII English text (compress'd data 16 bits)
dba102_asmb_20653.trc.Z: ASCII English text (compress'd data 16 bits)
由于我们只对文件名感兴趣,因此我们应用下一个命令 cut -d":" -f1,仅显示第一个字段:
alert_DBA102.log
alert_DBA102.log.Z
dba102_asmb_12307.trc.Z
dba102_asmb_20653.trc.Z
现在,我们希望使用 ls -l 命令,将上述列表作为参数进行传递,一次传递一个。xargs 命令允许您这样做。最后一部分,xargs ls -ltr,用于接收输出并对其执行 ls -ltr 命令,如下所示:
ls -ltr alert_DBA102.log
ls -ltr alert_DBA102.log.Z
ls -ltr dba102_asmb_12307.trc.Z
ls -ltr dba102_asmb_20653.trc.Z
因此,xargs 本身虽然没有多大用处,但在与其他命令相结合时,它的功能非常强大。
下面是另一个示例,我们希望计算这些文件中的行数:
$ file * | grep ASCII | cut -d":" -f1 | xargs wc -l
47853 alert_DBA102.log
19 dba102_cjq0_14493.trc
29053 dba102_mmnl_14497.trc
154 dba102_reco_14491.trc
43 dba102_rvwr_14518.trc
77122 total
(注:上述任务还可用以下命令完成:)
$ wc -l ‘file * | grep ASCII | cut -d":" -f1 | grep ASCII | cut -d":" -f1‘
该 xargs 版本用于阐释概念。Linux 可以用几种方法来完成同一个任务;请使用最适合您的情况的方法。
使用该方法,您可以快速重命名目录中的文件。
$ ls | xargs -t -i mv {} {}.bak
-i 选项告诉 xargs 用每项的名称替换 {}。-t 选项指示 xargs 先打印命令,然后再执行。
另一个非常有用的操作是当您使用 vi 打开要编辑的文件时:
$ file * | grep ASCII | cut -d":" -f1 | xargs vi
该命令使用 vi 逐个打开文件。当您希望搜索多个文件并打开它们进行编辑时,使用该命令非常方便。
它还有几个选项。最有用的可能是 -p 选项,它使操作具有可交互性:
$ file * | grep ASCII | cut -d":" -f1 | xargs -p vi
vi alert_DBA102.log dba102_cjq0_14493.trc dba102_mmnl_14497.trc
dba102_reco_14491.trc dba102_rvwr_14518.trc ?...
此处的 xarg 要求您在运行每个命令之前进行确认。如果您按下 "y",则执行命令。当您对文件进行某些可能有破坏且不可恢复的操作(如删除或覆盖)时,您会发现该选项非常有用。
-t 选项使用一个详细模式;它显示要运行的命令,是调试过程中一个非常有帮助的选项。
如果传递给 xargs 的输出为空怎么办?考虑以下命令:
$ file * | grep SSSSSS | cut -d":" -f1 | xargs -t wc -l wc -l 0 $
在此处,搜索 "SSSSSS" 后没有匹配的内容;因此 xargs 的输入均为空,如第二行所示(由于我们使用 -t 这个详细选项而产生的结果)。虽然这可能会有所帮助,但在某些情况下,如果没有要处理的内容,您可能希望停止 xargs;如果是这样,可以使用 -r 选项:
$ file * | grep SSSSSS | cut -d":" -f1 | xargs -t -r wc -l $
如果没有要运行的内容,该命令退出。
假设您希望使用 rm 命令(该命令将作为 xargs 命令的参数)删除文件。然而,rm 只能接受有限数量的参数。如果您的参数列表超出该限制怎么办?xargs 的 -n 选项限制单个命令行的参数个数。
下面显示了如何限制每个命令行仅使用两个参数:即使向 xargs ls -ltr 传递五个文件,但每次向 ls -ltr 仅传递两个文件。
$ file * | grep ASCII | cut -d":" -f1 | xargs -t -n2 ls -ltr
ls -ltr alert_DBA102.log dba102_cjq0_14493.trc
-rw-r----- 1 oracle dba 738 Aug 10 19:18 dba102_cjq0_14493.trc
-rw-r--r-- 1 oracle dba 2410225 Aug 13 05:31 alert_DBA102.log
ls -ltr dba102_mmnl_14497.trc dba102_reco_14491.trc
-rw-r----- 1 oracle dba 5386163 Aug 10 17:55 dba102_mmnl_14497.trc
-rw-r----- 1 oracle dba 6808 Aug 13 05:21 dba102_reco_14491.trc
ls -ltr dba102_rvwr_14518.trc
-rw-r----- 1 oracle dba 2087 Aug 10 04:30 dba102_rvwr_14518.trc
使用该方法,您可以快速重命名目录中的文件。
$ ls | xargs -t -i mv {} {}.bak
-i 选项告诉 xargs 用每项的名称替换 {}。
用途
构造参数列表并运行命令。
语法
xargs [ -p ] [ -t ] [ -e [ EOFString ] ] [ -E EOFString ] [ -i [ ReplaceString ] ] [ -I ReplaceString ] [ -l [ Number ] ] [ -L Number ] [ -n Number [ -x ] ] [ -s Size ] [ Command [ Argument ... ] ]
注: 不要在小写标志和参数之间放置空格。
描述
生成的命令行长度是 Command 和每个作为字符串对待的 Argument(包括每个字符串的空字节 终结符)的大小的总和(以字节为单位)。xargs 命令限制命令行的长度。 当构造的命令行运行时,组合的 Argument 和环境列表 不能超出 ARG_MAX 字节。在这个约束下,如果 不指定 -n 或 -s 标志,缺省命令行长度 至少是由LINE_MAX 指定的值。
标志
-e[EOFString] | 废弃的标志。请使用 -E 标志。 将 EOFString 参数用作逻辑 EOF 字符串。如果不 指定 -e 或 -E 标志, 则假定下划线(_)为逻辑 EOF 字符串。如果 不指定 EOFString 参数,则禁用逻辑 EOF 字符串 能力,且下划线按照字面含义使用。xargs 命令读取标准输入直到达到 EOF 或指定的字符串。 |
-E EOFString | 指定逻辑 EOF 字符串以替换缺省的下划线(_)。 xargs 命令读取标准输入直到达到 EOF 或指定的字符串。 |
-i[ReplaceString] | 废弃的标志。请使用 -I(大写 i)标志。 如果没有指定 ReplaceString 参数, 则使用字符串 "{}"。
注:-I(大写 i)和 -i 标志是互相排斥的;最后指定的标志生效。 |
-I ReplaceString | (大写 i)。插入标准输入的每一行作为 Command 参数的自变量,把它插入每个发生 ReplaceString 的 Argument中。ReplaceString 不能在超过 5 个自变量中使用。 在每个标准输入行开始的空字符被忽略。 每个 Argument 能包含一个或多个 ReplaceString,但不能大于 255 字节。-I 标志同样打开 -x 标志。
注:-I(大写 i)和 -i 标志是互相排斥的;最后指定的标志生效。 |
-l[Number] | (小写的 L)。废弃的标志。请使用 -L 标志。 如果没有指定 Number 参数,使用缺省值 1。-l 标志同样打开 -x 标志。
注: -L、-I(小写的 L)和 -n 标志是互相排斥的;最后指定的标志生效。 |
-L Number | 用从标准输入读取的指定行数的非空参数运行 Command 命令。如果保留少于指定的 Number,Command 参数 的最后调用可以有少数几个参数行。行以第一个换行字符结束,除非该行的最后一个字符是一个空格 或制表符。后续的空格表示延续至下一个非空行。
注: -L、-I(小写的 L)和 -n 标志是互相排斥的;最后指定的标志生效。 |
-n Number | 运行 Command 参数,且使用尽可能多的标准输入自变量,直到 Number 参数指定的最大值。如果满足以下条件,则xargs 命令使用 更少的自变量:
|
-p | 询问是否运行 Command 参数。 它显示构造的命令行,后跟一个 ?...(问号和省略号)提示。输入肯定的、特定于语言环境的响应 以运行 Command 参数。 任何其它响应都会引起 xargs 命令 跳过那个特定的参数调用。每个调用都将询问您。 -p 标志同样打开 -t 标志。 |
-s Size | 设置构造的 Command 行的最大 总大小。Size 参数必须是正整数。如果满足以下条件,则使用更少的自变量:
|
-t | 启用跟踪方式,并在运行之前将构造的 Command 行回送到标准错误。 |
-x | 如果有任何 Command 行大于 -s Size 标志指定的字节数,停止运行 xargs 命令。如果指定 -I(大写 i)或 -l(小写 L)标志,则打开 -x 标志。如果 没有指定 -i、-I(大写 i)、-l(小写 L)、-L 或 -n 标志,则 Command 行的总长度必须 在 -s Size 标志指定的限制内。 |
退出状态
该命令返回下列退出值:
0 | 所有 Command 参数的调用 都返回退出状态 0。 |
1-125 | 不能汇编满足指定需求的命令行, 一个或多个 Command 参数的调用 返回一个非零的退出状态,或发生一些其它的错误。 |
126 | Command 已找到但不能被调用。 |
127 | 找不到 Command。 |
如果不能汇编满足指定需求的命令行, 则不能调用这个命令,命令的调用被一个信号终止,或以退出状态 255 退出。xargs 命令将写一条诊断消息并 退出而不处理任何保留的输入。
示例
- 要对名称在文件中列出的文件使用命令,输入:
xargs lint -a <cfiles
如果 cfiles 文件包含下面的 文本:
main.c readit.c gettoken.c putobj.c
xargs 命令就构造并运行 下面的命令:
lint -a main.c readit.c gettoken.c putobj.c
如果 cfiles 文件包含的文件名比在单一 shell 命令行上能处理的文件名(最多 LINE_MAX)要多,xargs 命令会用后者运行 lint 命令。然后它使用余下的文件名构造并运 行另一个 lint 命令。 根据在 cfiles 文件中列出的名称, 命令看起来可能类似于如下所示的内容:
lint -a main.c readit.c gettoken.c . . . lint -a getisx.c getprp.c getpid.c . . . lint -a fltadd.c fltmult.c fltdiv.c . . .
该命令序列同用所有的文件名运行 lint 命令一次不完全一样。lint 命令检查文件之间的交叉参考。然而,在这个示例中, 它不能在 main.c 和 fltadd.c 文件之间,或任意两个在分开 的命令行上列出的文件之间进行检查。
由于这个原因, 仅当所有的文件名都在一行上列出时,才可能运行命令。要将这个指定 到 xargs命令,通过输入以下命令使用 -x 标志:
xargs -x lint -a <cfiles如果在文件 cfiles 中的所有 文件名没有在一个命令行上列出,xargs 命令 显示一条错误消息。 - 要构造包含一定数量文件名的命令,输入: 该命令序列构造并运行每个包含两个文件名的 diff 命令(-n 2):
diff starting chap1 diff concepts chap2 diff writing chap3
-t 标志使 在运行 xargs 命令前显示每个命令, 这样您可以看到正在发生的事件。<<EOF 和 EOF 模式匹配字符定义 一个 here document, 它把在结尾行之前输入的文本用作对 xargs 命令的标准输入。
- 要把文件名插入命令行的中间,输入: 该命令序列通过在每个名字结尾添加 .old 来重命名在当前目录里的所有文件。-I 标志告诉 xargs 命令插入有{} (花括号)出现的 ls 目录列表的每一行。 如果当前目录包含文件 chap1、chap2 和 chap3,这会构造下面的命令:
mv chap1 chap1.old mv chap2 chap2.old mv chap3 chap3.old
- 要对个别选择的文件运行命令,输入: 该命令序列允许选择文件以添加到 lib.a 库。-p 标志告诉 xargs 命令去 显示每个它构造的 ar命令,并询问是否想 运行它。输入 y 来运行命令。如果不想 运行这个命令按任意其它键。
会显示一些类似于下面的内容:
ar r lib.a chap1 ?... ar r lib.a chap2 ?... ar r lib.a chap3 ?...
- 要构造包含特定数量自变量的 命令并将那些自变量插入一个命令行的中间,输入:
ls | xargs -n6 | xargs -I{} echo {} - some files in the directory
如果当前目录 包含从 chap1 到 chap10 的文件,构造的输出将会是下列内容:
chap1 chap2 chap3 chap4 chap5 chap6 - some files in the directory chap7 chap8 chap9 chap10 - some file in the directory