使用 xargs 命令
xargs 命令读取标准的输入,然后使用参数作为输入构建和执行命令。如果没有给出命令,那么将使用 echo 命令。清单 12 是使用我们的 text1 文件的基础例子,它包含 3 个行,每行只有两个单词。
|
为什么 xargs 只有一行输出?默认情况下,xargs 在空格处中断输出,并且每个生成的标记都成为一个参数。不过,当 xargs 构建命令时,它将一次传递尽可能多的参数。您可以使用 -n 覆盖该行为,或使用 --max-args 参数。在清单 13 中,我们使用了这两种方法,并为使用 xargs 添加一个显式的 echo 调用。
|
如果输入包含由单引号或双引号保护的空格,或使用了斜杠进行转义,那么 xargs 将不在遇到这些空格时中断。清单 14 显示了这些空格点。
|
到目前为止,已经在命令的末尾添加了所有参数。如果您需要在这些参数后面再使用其他参数,可以使用 -I 选项指定一个替换字符串。如果 xargs 将要执行的命令包含有替换字符串,那么将使用参数替换它。进行了替换之后,仅将参数传递给每个命令。不过,将从一整行输出创建参数,而不仅是一个标记。您 还可以使用 xargs 的 -L 选项让命令将行当作参数看待,而不是默认的以单个空格分隔的标记。使用 -I 选项表示 -L 1。 清单 15 显示了使用 -I 和 -L 选项的例子。
|
尽管我们的例子为了便于演示使用了简单的文本文件,您很少看到包含这样的输入的 xargs。您通常需要处理某些 命令生成的大量文件,这些命令包括 ls、find 或 grep。清 单 16 显示了一种通过 xargs 将目录清单传递到命令(比如 grep)的方法。
|
如果上一个例子中的一个或多个文件名包含空格,那么会发生什么呢?如果您像清单 16 那样使用该命令,那么将得到一个错误。在实际情况中,文件列表可能来自一些源,比如定制脚本或命令,而不是 ls,或者您希望 通过其他管道线阶段传递它,以进一步进行过滤。所以您应该使用 grep "1" * 取代以上构造。
对于 ls 命令,您可以使用 --quoting-style 选项强制给导致问题的文件名加上引号或进行转义。另外一种更好的解决办法是使用 xargs 的 -0 选项,从而使用 null 字符串 (\0) 分隔输入参数。尽管 ls 没有提供使用 null 字符串分隔的文件名作为输出的选项,但许多命令都提供这样的选项。
在清单 17 中,我们首先将 text1 复制到 “text 1”,然后显示一些在 xargs 命令中使用包含空格的文件名列表的方法。这些示例仅为了演示概念,因为 xargs 可能更加复杂。尤其是在最后一个例子中, 如果一些文件名已经包含新行字符串,那么将新行字符串转换成 null 字符串将导致错误。在本文的下一个部分中,我们将查看另外一个更加健壮的解决方案,即使用 find 命令生成合适的以 null 字符串分隔的输出。
|
xargs 命令不会构建任意长度的命令。在 Linux 内核 2.26.3 之前,命令的长度是受限制的。针对某个包含大量名称很长的文件的目录的命令,比如 rm somepath/*,可能会失败, 返回的消息表明参数列表太长。在更旧的 Linux 系统或 UNIX 系统上仍然存在该限制,因此了解如何使用 xargs 以处理这种问题非常有用。
您可以使用 --show-limits 选项显示 xargs 的默认限制,然后使用 -s 选项将输出命令的长度限制在允许的最大字符串数量之内。查看手册页了解其他未能再次讨论的选项。
使用带有 -exec 选项或 xargs 的 find 命令
在文章 “学习 Linux,101:文件和目录管理” 中,您学习例如如何使用 find 命令根据名称、修改时间、大小或其他特征查找文件。找到匹配的文件集之后,您通常希望对它们执行某些操作:删除、移动和重命名它们等。现在我们看一下 find 命令的 -exec 选项,其功能类似于使用 find 并通过管道将输出指向 xargs。
|
与前面学习的 xargs 命令相比,它有几个不同之处。
- 您必须使用 {} 标记文件名在命令中的位置。它不是自动添加在末尾的。
- 您必须使用转义后的分号终止该命令,比如 \;、';' 或 ";" 都行。
- 该命令对每个输入文件执行一次。
尝试运行 find text[12] |xargs cat text3 亲自看看区别在哪里。
现在,我将话题转回到文件名中的空格。在清单 19 中我们尝试使用带有 -exec 的 find, 而不是带有 xargs 的 ls。
清单 19. 对包含空格的文件名使用 find 和 -exec
|
到目前为止,一切进展顺利。但是不是缺少了什么?哪个文件包含 grep 找到行?缺少了文件名,因为 find 为每个文件调用 grep 一次,而 grep 非常智能,能够知道您是不是仅提供文件名,您不需要它告诉您是哪个文件。
我们也可以改为使用 xargs,但我们已经看到了文件名中包含空格时出现的问题。我们还提到 find 可以生成一个以 null 分隔符分隔的文件名列表,这是 -print0 选项所起的作用。新的 find 可能使用加号(+)取代分号(;)作为分隔符,这允许 find 在一次调用命令时传递尽可能多的名称,类似于 xargs。 在这种情况中,仅能使用 {} 一次,并且它必须是该命令的最后一个参数。清单 20 显示了这两种方法。
清单 20. 对包含空格的文件名使用 find 和 xargs
|
一般而言,两种方法都是有效的,选择哪种方法由您决定。记住,使用管道导出包含未受保护的空格的内容将导致问题,因此如果您要使用管道将输出 导出到 xargs,请使用将 -print0 选项和 find 结合使用,并使用 -0 选项告诉 xargs 接收使用 null 分隔符分隔的输入。其他命令,包括 tar,也支持使用 -0 选项并用 null 分隔符分隔的输入,因此应该对支持该选项的命令使用它,除非您能确保您的输入列表不会造成问题。
最后,我们介绍对文件列表进行操作。在执行删除或重命名文件等重要操作之前,最好彻底地测试列表和仔细测试命令。进行良好的备份也是非常有价 值的。
- jarson's blog
- Login or register to post comments

最新回应
5 hours 21 min 之前
15 weeks 6 days 之前
47 weeks 16 hours 之前
1 year 7 weeks 之前
1 year 7 weeks 之前
1 year 14 weeks 之前
1 year 16 weeks 之前
1 year 19 weeks 之前
1 year 21 weeks 之前
1 year 21 weeks 之前