什么时候会`找到。 -exec COMMAND {} +` 多次执行 COMMAND?

什么时候会`找到。 -exec COMMAND {} +` 多次执行 COMMAND?

如果我做

find . -exec echo {} +

它将所有路径打印在一行中,即命令echo仅执行一次。

但根据man find

-exec command {} +
    ... the number of invocations of the command will 
be much  less  than  the  number  of matched files. ...

似乎在某些情况下该命令会被执行多次。我对吗?请举例说明。

答案1

POSIX 定义find -exec utility_name [参数...] {} +作为:

主要表达式的末尾应以 <分号> 或 <加号> 标点。只有紧跟在仅包含两个字符“{}”的参数后面的 <plus-sign> 才能标点主表达式的末尾。 <加号> 的其他用途不应被视为特殊用途。如果主要表达式由 <分号> 标点,则该实用程序实用程序名称应为每个路径名调用一次,如果实用程序返回零值作为退出状态,则主路径应评估为 true。 A实用程序名称或者争论仅包含两个字符“{}”应替换为当前路径名。如果一个实用程序名称或者争论string 包含两个字符“{}”,但不仅仅是两个字符“{}”,是否是实现定义的寻找替换这两个字符或不加更改地使用该字符串。

如果主表达式由 <加号> 标点,则主表达式应始终评估为 true,并且评估主表达式的路径名应聚合到集合中。实用性实用程序名称 应为每组聚合路径名调用一次。每次调用应在集合中的最后一个路径名聚合之后开始,并应在寻找实用程序退出,并且在为此主项聚合下一组(如果有)中的第一个路径名之前,但未指定调用是否发生在其他主项评估之前、期间或之后。如果任何调用返回非零值作为退出状态,则寻找 实用程序应返回非零退出状态。仅包含两个字符“{}”的参数应替换为聚合路径名集,每个路径名按照聚合顺序作为单独的参数传递给调用的实用程序。任何两个或多个路径名集合的大小应受到限制,以便实用程序的执行不会导致超出系统的 {ARG_MAX} 限制。如果存在多个包含两个字符“{}”的参数,则行为未指定。

当你找到的文件名长度设置超过 system 时ARG_MAX,该命令被执行。

你可以ARG_MAX使用获取配置文件:

$ getconf ARG_MAX
2097152

在某些系统上, 的实际值ARG_MAX可能会有所不同,您可以参考这里更多细节。

答案2

POSIX 系统中新进程的参数列表有最大长度。find如果文件路径长于此,将分割执行。要查看 Linux 上的限制,请使用xargs --show-limits(不适用于 Mac OS,如果有人知道更好的替代方案,请在此处评论)

编辑:直接从 Gnouc 的答案中窃取,获取参数列表最大长度的 POSIX 方法是getconf ARG_MAX。然而,我在我的 mac os 机器上进行了一项实验,看起来find使用的数量略多于这个数字的一​​半。这与以下事实是一致的:在它工作的系统上,xargs --show-limits告诉我们它将不会使用最大参数长度(在这种情况下,它也会使用大约一半的数字),但是我找不到解释为了那个原因。

编辑2:似乎确定find每次调用将有多少参数粘在一起的唯一可靠方法是进行实验,例如通过运行

find / -exec echo {} + | wc -cl

由于每次调用的输出find都有一行echo,因此可以使用 来对它们进行计数wc -l。 ed的总字节数echo是相反的输出wc -c。将一个除以另一个,您将得到每个命令调用的参数中的平均字节数(尽管由于四舍五入,该值略低,但大约是系统中路径平均长度的一半)

相关内容