Answers:
最好用一个例子来说明。假设find打开了这些文件:
file1
file2
file3
使用-exec用分号(find . -exec ls '{}' \;),将执行
ls file1
ls file2
ls file3
但是,如果您使用加号代替(find . -exec ls '{}' \+),则将尽可能多的文件名作为参数传递给单个命令:
ls file1 file2 file3
文件名的数量仅受系统最大命令行长度的限制。如果命令超过此长度,则该命令将被多次调用。
+关联-exec总是被转义,但是+与关联-mtime却不是。你知道原因吗?我猜这是逃避;与关联的习惯-exec。
;。无法想象有必要逃脱+
到目前为止,所有答案都是正确的。我提供此信息是(对我来说)使用echo而不是来更清楚地说明所描述的行为ls:
对于分号,echo每个找到的文件(或其他文件系统对象)将调用一次命令:
$ find . -name 'test*' -exec echo {} \;
./test.c
./test.cpp
./test.new
./test.php
./test.py
./test.sh
带加号的命令echo仅被调用一次。找到的每个文件都作为参数传递。
$ find . -name 'test*' -exec echo {} \+
./test.c ./test.cpp ./test.new ./test.php ./test.py ./test.sh
如果find出现大量结果,您可能会发现该命令在参数数量上被阻塞。
xargs做的...从原则上讲,它永远不会阻塞太多的争论。
find都将尝试避免达到参数数量的限制。包括Solaris'(至少10个)。如果您做类似find ... -exec ksh -c 'cmd "$@" "$@"' sh {} +或的事情find ... -exec ksh -c 'files="$*" cmd "$@"' sh {} +,它可能会失败,但find不能为此而怪罪。请注意,GNU find是最后find要支持的实现之一+(曾经是将脚本移植到GNU系统的一种痛苦)。
来自man find:
-exec命令;
执行命令;如果返回0状态,则为true。后面的所有要查找的参数都将被视为命令的参数,直到由';'组成的参数为止 遇到。字符串'{}'被当前文件名替换,该文件名在命令的参数中出现的所有位置(而不仅仅是在单独的参数中,如在find的某些版本中)都在处理。这两种构造都可能需要转义(带有'\')或加引号,以防止它们被外壳扩展。有关使用'-exec'选项的示例,请参见示例秒部分。对于每个匹配的文件,指定的命令运行一次。 该命令在起始目录中执行。围绕-exec选项的使用存在不可避免的安全性问题。
-exec命令{} +
-exec选项的此变体在选定的文件上运行指定的命令,但是通过在末尾附加每个选定的文件名来构建命令行;该命令的调用总数将远远少于匹配文件的数目。命令行的构建与xargs构建命令行的方式几乎相同。命令中仅允许使用一个'{}'实例。该命令在起始目录中执行。
因此,据我了解,它对所\;找到的每个文件执行单独的命令find,而\+追加文件并在所有文件上执行单个命令。该\是一个转义字符,所以它是:
ls testdir1; ls testdir2
与
ls testdir1 testdir2
在我的shell中执行上述操作即可反映您问题中的输出。
\+假设有两个文件,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):
find *.tmp -exec diff {} \+
1c1,3
< 1
---
> 0
> 2
> 30
因此,在这种情况下diff 1.tmp; diff 2.tmp,diff 1.tmp 2.tmp
在某些情况下\;适当且\+必要。使用\+with rm是这样的一种情况,如果要删除大量文件,性能(速度)将优于\;。
find具有特殊的语法。您按{}原样使用,因为它们的含义是找到所找到文件的路径名,并且(大多数)shell不会以其他方式解释它们。您需要反斜杠,\;因为分号对shell有意义,它在find获得外壳之前先将其吃光了。因此find,在传递给C程序的参数列表中,要看完外壳之后要看的是:
“ -exec”,“ rm”,“ {}”,“;”
但是您需要\;在命令行上通过外壳将分号传递给参数。
您可以避免,\{\}因为shell引用的解释\{\}是just {}。同样,您可以使用'{}'。
你不能做的就是使用
-exec 'rm {} ;'
因为外壳程序将其解释为一个参数,
“ -exec”,“ rm {};”
而rm {} ;不是命令的名称。(至少除非有人真的搞砸了。)
更新资料
区别在于
$ ls file1
$ ls file2
和
$ ls file1 file2
该+被catenating名称到一个命令行。
;(分号)或+(加号)之间的区别在于参数如何传递到find的-exec/ -execdir参数中。例如:
using ;将执行多个命令(每个参数分别执行),
例:
$ find /etc/rc* -exec echo Arg: {} ';'
Arg: /etc/rc.common
Arg: /etc/rc.common~previous
Arg: /etc/rc.local
Arg: /etc/rc.netboot
后面的所有自变量
find均作为命令的自变量。该字符串
{}将替换为当前正在处理的文件名。
using +将执行最少的命令(因为参数组合在一起)。这与xargs命令的工作原理非常相似,因此它将在每个命令中使用尽可能多的参数,以避免超出每行参数的最大限制。
例:
$ find /etc/rc* -exec echo Arg: {} '+'
Arg: /etc/rc.common /etc/rc.common~previous /etc/rc.local /etc/rc.netboot
通过在每个末尾附加每个选定的文件名来构建命令行。
命令中仅
{}允许的一个实例。
也可以看看: