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

rah*_*hmu 38 bash pipe find xargs

我知道-exec可以+选择模仿xargs. 是否存在您更喜欢一种形式而不是另一种形式的情况?

我个人倾向于更喜欢第一种形式,如果只是为了避免使用管道。我find相信开发人员一定已经做了适当的优化。我对么?

jw0*_*013 27

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

  • `find ... -exec ... {} +` 的可移植性的一个显着例外是 OpenBSD,它只在 2012 年发布的 5.1 版中才获得了这个特性。所有 BSD 已经有 `-print0` 好几年了,即使是 OpenBSD(尽管它抵制该功能也有一段时间)。另一方面,Solaris 坚持使用 POSIX 功能,因此您会得到 `-exec +` 而没有 `-print0`。 (6认同)
  • 我不明白 `-0` 比 `--delimiter "\n"` 更痛苦。 (4认同)
  • 除了 `-0` 之外,GNU `xargs` 还需要 `-r` 来避免在没有输入的情况下运行命令。 (3认同)
  • `|的另一个问题 xargs -r0 cmd` 是 `cmd` 的 stdin 受到影响(取决于 `xargs` 实现,它是 `/dev/null` 或管道。 (2认同)

use*_*own 24

您可能想要链接调用以查找(曾经,当您了解到这是可能的,这可能是今天)。当然,这只有在您继续使用 find 时才有可能。一旦您通过管道传输到 xargs,它就超出了范围。

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

cat a.lst
fuddel.sh
fiddel.sh

cat b.lst
fuddel.sh
Run Code Online (Sandbox Code Playgroud)

这里没有技巧 - 只是两个都包含“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
Run Code Online (Sandbox Code Playgroud)

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

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

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

所以你不会离开 find 链,这是一件很方便的事情。我认为使用 -xargs 没有任何优势,因为您必须小心传递文件,而 find 不需要这样做 - 它会自动将每个文件作为单个参数传递给您。

如果您认为需要对 finds {} 括号进行一些掩码,请随时访问我的问题,该问题要求提供证据。我的主张是:你没有。

  • 这篇文章让我看到了一种使用“find”的新方法。非常感谢! (3认同)

Ale*_*ios 11

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

using 的一大优点xargs是能够使用xargs -P. 在多核系统上,这可以节省大量时间。

  • 你的意思是“-P”而不是“-p”。请记住,`xargs -P` 不在 POSIX 标准中,而 `find -exec {} +` 是,如果您想要可移植性,这很重要。 (7认同)

phk*_*phk 8

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

[用-exec … +]查找可能比某些用法效率低xargs;例如,xargs允许在前一个命令仍在执行时建立新的命令行,并允许您指定要并行运行的多个命令。然而,该find ... -exec ... +构造具有广泛的可移植性的优点。-exec ... +直到版本 4.2.12 [2005 年 1 月],GNU findutils 才支持“ ” ;这样做的原因之一是它-print0在任何情况下都已经有了 ' ' 动作。

我不太确定那是什么意思,所以我在聊天中询问derobert 是如何解释的:

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

(由我格式化。)

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

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