如果我做
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
。将一个除以另一个,您将得到每个命令调用的参数中的平均字节数(尽管由于四舍五入,该值略低,但大约是系统中路径平均长度的一半)