在find中使用分号(;)vs plus(+)和exec

为什么在使用之间的输出有差异

find . -exec ls '{}' \+ 

 find . -exec ls '{}' \; 

我有:

 $ find . -exec ls \{\} \+ ./file1 ./file2 .: file1 file2 testdir1 ./testdir1: testdir2 ./testdir1/testdir2: $ find . -exec ls \{\} \; file1 file2 testdir1 testdir2 ./file2 ./file1 

举一个例子可以很好地说明这一点。 比方说, find这些文件:

 file1 file2 file3 

使用-exec和分号( find . -exec ls '{}' \; )将执行

 ls file1 ls file2 ls file3 

但是,如果使用加号( find . -exec ls '{}' \+ ),尽可能多的文件名作为parameter passing给单个命令:

 ls file1 file2 file3 

文件名的数量只受系统最大命令行长度的限制。 如果该命令超过这个长度,该命令将被多次调用。

到目前为止所有的答案都是正确的。 我提供这个作为一个更清晰的(对我来说)使用echo而不是ls描述的行为的演示:

使用分号,命令echo会在每个文件(或其他文件系统对象)中被调用一次:

 $ find . -name 'test*' -exec echo {} \; ./test.c ./test.cpp ./test.new ./test.php ./test.py ./test.sh 

有了plus,命令echo只被调用一次。 find的每个文件都作为参数传入。

 $ find . -name 'test*' -exec echo {} \+ ./test.c ./test.cpp ./test.new ./test.php ./test.py ./test.sh 

如果find大量的结果,你可能会发现命令被称为扼stream圈的参数的数量。

从男人

-exec命令;

执行命令; 如果返回0状态,则返回true。 以下所有的参数都被认为是命令的参数,直到由“;”组成的参数 遇到。 string“{}”被replace为当前文件名,在它发生在命令的参数中的任何地方都被处理,而不仅仅是在单独的参数中,就像在某些版本的find中一样。 这两个构造都可能需要被转义(用'\')或引号来保护它们免受shell的扩展。 有关使用“-exec”选项的示例,请参阅EXAMPLES部分。 指定的命令对每个匹配的文件运行一次。 该命令在起始目录中执行。 围绕使用-exec选项有一些不可避免的安全问题; 您应该使用-execdir选项。

-exec命令{} +

-exec选项的这种变体在所选文件上运行指定的命令,但是命令行是通过在最后附加每个选定的文件名来构build的; 该命令的总调用次数将远远less于匹配文件的数量。 命令行的构build方式与xargs构build其命令行的方式大致相同。 命令中只允许有一个“{}”实例。 该命令在起始目录中执行。

所以我理解它的方式, 执行单独的命令和+追加每个名字。 它基本上是被执行的方式,因为“逃脱”就是这样

 ls testdir1; ls testdir2 

VS

 ls testdir1 testdir2 

在我的shell中执行上述操作可以将输出映射到您的问题。

更新2

那么,你为什么要使用+

说我有两个文件1.tmp和2.tmp

1.tmp

1
2
3

2.tmp

0
2
3

赛跑

  find *.tmp -exec diff {} \; > diff: missing operand after `1.tmp' > diff: Try `diff --help' for more information. > diff: missing operand after `2.tmp' > diff: Try `diff --help' for more information. 

如果您使用+并连接查找结果,如下所示:

 find *.tmp -exec diff {} \+ 1c1,3 < 1 --- > 0 > 2 > 30 

所以在这种情况下它的差异1.tmp; diff 2.tmp和diff 1.tmp 2.tmp

有些情况下\; 是合适的,+将是必要的。 使用rm就是这样一个例子,如果你在删除大量文件的速度大大提高的话。 我总是喜欢学习更多关于发现,它是如此强大和方便的实用程序,我希望这足以解释的差异。

这是处理: find有特殊的语法。 你可以直接使用{} ,因为它们有意义地findfind的文件的path名,(大多数)shell不能解释它们。 你需要反斜杠\; 因为分号对shell有意义,在find之前就吃了。 那么,在传递给C程序的参数列表中, 发现想要在shell之后发现的东西是

“-exec”,“rm”,“{}”,“;”

但你需要\; 在命令行上通过shell获取分号给参数。

你可以用\{\}因为\{\}的shell引用解释就是{} 。 同样,您可以使用“{}”。

不能做的是使用

  -exec 'rm {} ;' 

因为壳解释为一个参数,

“-exec”,“rm {};”

和“rm {}”; 不是一个命令的名字。 (至less除非有人真的搞砸了。)

更新

区别在于

 $ ls file1 $ ls file2 

 $ ls file1 file2 

+正在命令行上命名。

之间的区别; (分号)或+ (加号)是如何将parameter passing到find的-exec / -execdir参数。 例如:

  • 使用; 将执行多个命令 (分别为每个参数),

    例:

     $ find /etc/rc* -exec echo Arg: {} ';' Arg: /etc/rc.common Arg: /etc/rc.common~previous Arg: /etc/rc.local Arg: /etc/rc.netboot 

    接下来的所有参数都被认为是命令的参数。

    string{}被replace为正在处理的当前文件名称。

  • 使用+会执行尽可能less的命令 (因为参数组合在一起)。 这与xargs命令的工作原理非常相似,所以它将尽可能多地使用每个命令的参数,以避免超过每行参数的最大限制。

    例:

     $ find /etc/rc* -exec echo Arg: {} '+' Arg: /etc/rc.common /etc/rc.common~previous /etc/rc.local /etc/rc.netboot 

    命令行是通过在最后附加每个选定的文件名来构build的。

    在命令中只允许有一个{}实例。

也可以看看:

  • man find
  • 在SO中使用分号(;)和加号(+)来执行find
  • 简单的unix命令,什么是{}和\; 在SO
  • find的-exec命令中的{} +是什么意思? 在Unix上

我们正在努力寻找pipe家的档案。

找 。 -exec echo {} \; 命令跑了一晚,最后没有结果。

找 。 -exec echo {} \ +有结果,只花了几个小时。

希望这可以帮助。