查找-exec + vs查找| xargs:选择哪一个?


32

我了解-exec可以+选择模拟的行为xargs。在任何情况下,您都喜欢一种形式而不是另一种形式吗?

如果只是避免使用管道,我个人倾向于使用第一种形式。我确定肯定开发人员find必须进行适当的优化。我对么?

Answers:


21

您可能希望链接呼叫以进行查找(一旦了解,就有可能,可能是今天)。当然,这只有在您继续寻找的情况下才有可能。一旦通过管道传递给xargs,它就超出范围了。

小示例,两个文件a.lst和b.lst:

cat a.lst
fuddel.sh
fiddel.sh

cat b.lst
fuddel.sh

这里没有技巧-只是事实都包含“ fuddel”,而只有一个包含“ fiddel”。

假设我们不知道。我们搜索符合2个条件的文件:

find -exec grep -q fuddel {} ";" -exec grep -q fiddel {} ";" -ls
192097    4 -rw-r--r--   1 stefan   stefan         20 Jun 27 17:05 ./a.lst

好吧,也许您知道grep或其他程序将两个字符串都作为条件传递的语法,但这不是重点。给定文件作为参数,每个可以返回true或false的程序都可以在这里使用-grep只是一个受欢迎的示例。

请注意,您可以在find -exec之后加上其他find命令,例如-ls-delete或类似的命令。注意,删除不仅会删除rm(删除文件),还会删除rmdir(删除目录)。

只要没有另外指定(即使用-or开关(和括号(需要屏蔽))),则将这样的链读取为命令的AND组合。

因此,您不必离开查找链,这很方便。我看不到使用-xargs的任何优势,因为您在传递文件时必须小心,这是find不需要做的事情-它会自动将每个文件作为单个参数传递给您。

如果您认为自己的{}花括号需要遮罩,请随时访问我的问题以寻求证据。我的主张是:您没有。


3
这篇文章使我看到了一种新的使用方法find。非常感谢!
rahmu 2013年

1
“使用-xargs没有任何优势”。怎样-execxargs -P4才能使四个内核中的三个不处于空闲状态?
Damian Yerrick '16

1
@DamianYerrick:不以“;”结尾的-exec命令 但带有+(/加号)。
不知名的使用者

25

安全地传递文件名到xargs要求您find支持该-print0选项,并且您xargs具有相应的选项来读取它(--null-0)。否则,文件名中带有不可打印字符,反斜杠,引号或空格的文件名可能会导致意外行为。另一方面,find -exec {} +它属于POSIX find规范,因此是可移植的,并且与一样安全find -print0 | xargs -0,并且绝对比更加安全find | xargs。我建议你从来没有这样做find | xargs没有-print0


6
find … -exec … {} +OpenBSD 的可移植性是一个明显的例外,它仅在2012年发布的5.1版中获得了此功能。所有BSD都已经-print0使用了几年,甚至OpenBSD(尽管它也抵制了该功能一段时间)。另一方面,Solaris坚持使用POSIX功能,因此您获得了-exec +no -print0
吉尔斯(Gillles)“所以-别再邪恶了”

-print0这是很痛苦的,尽管您可以说这xargs --delimiter "\n"是不相等的,但是在发现后者之前,我从未使用过前者。
Sridhar Sarnobat,2015年

3
我看不出有什么-0比痛苦更痛苦的了--delimiter "\n"
jw013

2
除了-0,如果没有输入,GNU还xargs需要-r避免运行该命令。
斯特凡Chazelas

2
的另一个问题| xargs -r0 cmdcmdstdin会受到影响(取决于xargs实现方式,它是/dev/null管道还是管道。
StéphaneChazelas 2015年

10

如果使用-exec ... ;表单(记住要转义分号),则每个文件名将运行一次命令。如果使用-print0 | xargs -0,则每个文件名运行多个命令。您绝对应该使用该-exec +表格,该表格将多个文件放在一个命令行中,并且在涉及大量文件时会更快。

using的一大优点是可以使用xargs并行运行多个命令xargs -P。在多核系统上,可以节省大量时间。


6
您的意思-P不是-p。请记住,xargs -P它不是POSIX标准中的一个,但是find -exec {} +,如果您要进行可移植性,那么这很重要。
jw013 2012年

@Alexios您不必转义加号,因为它对shell没有特殊含义:find /tmp/ -exec ls "{}" +可以正常工作。
丹尼尔·库尔曼2012年

1
科伦特,当然。我已经逃避了-exec很久以后的所有事情(我是受虐狂,我什至不使用引号来转义{},我总是键入\{\};不要问),一切看起来现在都必须转义。
Alexios 2012年

1
@Alexios:如果您发现一个例子(除了受虐狂之外)对括号的屏蔽很有用,请在此处提供它作为对我问题的答案-afaik此提示已过时,仅在联机帮助页中显示为遗物。我从未见过无法解决问题的示例find /tmp/ -exec ls {} +
用户未知

1
对我来说,这是SunOS 4时代形成的肌肉记忆。由于我已经做了多年,所以完全不知道何时bash开始逐字接受括号。我敢肯定,如果不逃脱牙套,我至少会用一个旧的贝壳扔出适合的形状。
Alexios 2012年

8

关于性能,我认为这样做-exec … +会更好,因为它是完成所有工作的单个工具,但是GNU findutil文档的一部分说,-exec … +在某些情况下可能效率较低:

[找到-exec … +]可能比某些用途的效率低xargs; 例如,xargs允许在上一条命令仍在执行时建立新的命令行,并允许您指定要并行运行的许多命令。但是,该find ... -exec ... +构造具有可移植性广的优点。GNU findutils -exec ... +直到4.2.12版[2005年1月]才支持' ' 。原因之一是,-print0无论如何它都已经执行了“ ”操作。

我不确定这是什么意思,所以我在聊天中问derobert在哪里解释为:

find可能-exec … +正在运行时继续搜索下一批文件,但不是这样。
find … | xargs …这样做是因为查找是一个不同的过程,并且它将一直运行直到管道缓冲区填满

(由我格式化。)

就是这样。但是,如果性能真的很重要,则您必须进行实际的基准测试,甚至问自己是否在这种情况下甚至想使用shell。

在此站点上,我认为最好是建议人们尽可能使用该-exec … +表单,这是因为它更简单,并且出于此处其他答案中提到的原因(例如,无需考虑太多即可处理奇怪的文件名)。

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.