“ xargs”和命令替换之间的区别?


14

在许多情况下,我使用命令替换代替xargs。例如rm $(ls)ls | xargs rm

它们之间到底有什么区别?

我认为区别之一是命令替换在子shell中xargs运行,而在当前shell中运行,但是我不确定。

请列出差异。

Answers:


9

一个区别是,使用命令替换而不是管道时,传递的数据大小受命令缓冲区的大小限制,因此在某些情况下会被截断而不会发出警告。这也意味着必须将整个命令输出传递给下一个命令,然后将其生成并存储在内存中,因此,对于大型输出,您可以使用比必要更多的内存。

第一种方法的另一个问题是,输出是在空白处分割的,因此您不能处理包含空格的文件名。xargs也受空白问题的影响,但是可以通过更改使用的定界符来解决。为了顺便正确地处理文件名,在第二个示例中,您将需要使用空字节作为分隔符。

第三个问题是全局扩展,因此,如果文件名中带有星号或问号,则会出现意外结果。

您可以在此处找到关于此问题的精彩讨论:http : //mywiki.wooledge.org/ParsingLs

正确的语法是

echo rm *

或者,如果您必须使用xargs,

find . -maxdepth 1 -print0 | xargs -0 echo rm

echo当输出看起来正确时,将其删除。


1
@Sinoosh:xargs由于管道的缘故,它也将在子shell中运行,除非您启用shopt -s lastpipe,在这种情况下它将在当前shell中运行。我不认为在这种情况下在子shell中运行不是问题,因为您无需更改任何变量。
user000001

1
@Sinoosh:要逐个传递参数,可以使用-l标记,例如find . -maxdepth 1 -print0 | xargs -0 -l rm。对于第二个问题,您不能使用ls lsxargs -0因为ls不会在null分支上拆分输出,而是使用换行符(在文件名BTW中有效)
user000001

1
@Sinoosh:不是第一段,而是第二段:不带-0选项的xargs 遇到空白问题。
user000001

1
阅读man xargs,使用echo进行测试,没有rmxargs让我们超过了Shell限制(某些缓冲区限制为65K,而文件名列表则没有)。
waltinator '16

1
@Sinoosh:我没有一个很好的参考手册,但是您可以键入,xargs --show-limits然后您会看到系统上设置的限制,
user000001
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.