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


9

如果我做

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. ...

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

Answers:


8

POSIX将find -exec utility_name [argument ...] {} +定义为:

主表达式的末尾应用<semicolon>或<plus-sign>标点。只有紧跟在仅包含两个字符“ {}”的参数之后的<plus-sign>才应标出主表达式的末尾。<plus-sign>的其他用途不应视为特殊用途。如果主表达式用<semicolon>标点,则为每个路径名调用一次实用程序Utility_name,并且如果该实用程序返回零值作为退出状态,则主程序应评估为true。仅包含两个字符“ {}” 的Utility_name或自变量应替换为当前路径名。如果是utility_name参数string包含两个字符“ {}”,而不仅仅是两个字符“ {}”,它是实现定义的,查找是替换这两个字符还是使用不更改的字符串。

如果主表达式用<plus-sign>进行标点,则主表达式应始终评估为true,并且为其评估主表达式的路径名应汇总为集合。 对于每组聚合路径名,应一次调用实用程序Utility_name。每次调用应在集合中的最后一个路径名聚合之后开始,并且应在find实用程序退出之前和为此主要对象的下一个集合中的第一个路径名(如果有)聚合之前完成,但是在其他方面未指定在其他原色的评估之前,之中或之后发生。如果有任何调用返回非零值作为退出状态,则查找 实用程序应返回非零退出状态。仅包含两个字符“ {}”的参数应由一组聚集的路径名代替,每个路径名均作为一个单独的参数以与聚集的顺序相同的方式传递给被调用的实用程序。必须限制两个或多个路径名的任何集合的大小,以使实用程序的执行不会导致超出系统的{ARG_MAX}限制。如果存在多个包含两个字符“ {}”的参数,则行为未指定。

当找到的文件名长度集超过system时ARG_MAX,将执行命令。

您可以ARG_MAX使用getconf

$ getconf ARG_MAX
2097152

在某些系统上,的实际值ARG_MAX可能会有所不同,有关更多详细信息,请参见此处


我进行了一个实验,使用find / -exec echo | wc并测量了字符数和行数之间的比率,发现使用的最大命令行长度find显着小于理论POSIX限制,并且更接近于Size of command buffer we are actually using的输出xargs --show-limits。这对于Linux是正确的find,但对于Mac OS的实现可能也是如此,尽管xargs不会在Mac OS中显示该值。知道为什么会这样吗?
pqnet 2014年

--show-limitsPOSIX未指定,Mac OS的实现xargs不支持它。find / -exec echo | wc将无法正常工作。请记住,ARG_MAX返回字节。这是exec(3)函数参数的最大长度。
cuonglm

我知道--show-limits不是POSIX,尽管这不是所使用的最大参数长度find,后者使用的值较小。我不明白您为什么这么说是find / -exec echo | wc行不通的:我认为这是估算实际价值的好方法(据我所见,这比使用更好getconf ARG_MAX)。另外,我的文件系统大部分都是(如果不是全部)ASCII字符,因此字符数与字节数大致相同。
pqnet 2014年

@pqnet:使用find / -exec sh -c 'echo $@ | wc -c' _ {} +nottead。
cuonglm

抱歉,我写错了,我实际上使用过find / -exec echo {} + | wc -lc
pqnet 2014年

7

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 -lechoed 的总字节数是的输出wc -c。彼此除以得到每个命令调用的参数中的平均字节数(尽管由于取整,该值略低,大约是系统中路径平均长度的一半)


xargs不使用完整的最大参数长度,因为许多程序会在前面附加一些其他参数,然后将这些参数传递给其他程序。如果xargs将参数填充到绝对最大值,则此类程序将中断,因为这些多余的参数将没有空间。
2014年

@hvd很有道理。但是,然后,有一种POSIX方法可以知道xargsor 使用了多少缓冲区find
pqnet 2014年

您可以使用很长的参数列表来执行它,确定第一次调用中传递了多少个参数(类似yes . | xargs | head -n 1 | wc -c),并将其与的输出进行比较getconf ARG_MAX。但是,实际上,在我的系统上进行尝试时,我得到的差异是如此之大,以至于似乎还有很多我所不知道的事情。
2014年

因此归结为实验...我将更新我的答案
pqnet 2014年
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.