为什么使用的输出有差异

find . -exec ls '{}' \+

and

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有特殊的语法。您可以使用{},因为它们作为所找到文件的路径名具有查找的意义,并且(大多数)shell不会解释它们。你需要反斜杠\;因为分号对shell有意义,它会在find得到它之前把它吃掉。所以find希望在shell完成后,在传递给C程序的参数列表中看到的是

"-exec", "rm", "{}", ";"

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

您可以使用\{\},因为\{\}的shell引号解释只是{}。类似地,您可以使用'{}'。

你不能做的是使用

 -exec 'rm {} ;'

因为shell将其解释为一个参数,

"-exec", "rm {};"

和rm {};不是命令的名称。(至少除非有人真的在鬼混。)

更新

区别在于

$ ls file1
$ ls file2

and

$ ls file1 file2

+是将名称串联到命令行上。


从人类发现:

-exec命令;

Execute command; true if 0 status is returned. All following arguments to find are taken to be arguments to the command until an argument consisting of ';' is encountered. The string '{}' is replaced by the current file name being processed everywhere it occurs in the arguments to the command, not just in arguments where it is alone, as in some versions of find. Both of these constructions might need to be escaped (with a '\') or quoted to protect them from expansion by the shell. See the EXAMPLES sec section for examples of the use of the '-exec' option. The specified command is run once for each matched file. The command is executed in the starting directory. There are unavoidable security problems surrounding use of the -exec option; you should use the -execdir option instead.

-exec命令{}+

-exec选项的这个变体在 所选文件,但是命令行是通过追加来构建的 每个选定的文件名的末尾;总数量 命令的调用次数将远远少于 匹配的文件。命令行也是以同样的方式构建的 xargs构建它的命令行。只有一个“{}”实例 在命令中允许。命令在 起始目录。

所以,在我的理解中,\;为find找到的每个文件执行一个单独的命令,而\+附加文件并对所有文件执行一个命令。\是转义字符,所以它是:

ls testdir1; ls testdir2 

vs

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。tmp;Diff 2.tmp和Diff 1.tmp

有些情况下\;是合适的,\+将是必要的。在rm中使用\+就是这样一个例子,如果你要删除大量的文件,性能(速度)将优于\;


这可以用一个例子来最好地说明。让我们说find会找到这些文件:

file1
file2
file3

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

ls file1
ls file2
ls file3

但如果你用加号代替(找到。-exec ls '{}' \+),将尽可能多的文件名作为参数传递给单个命令:

ls file1 file2 file3

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


到目前为止所有的答案都是正确的。我提供了一个更清晰的(对我来说)使用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显示大量结果,您可能会发现所调用的命令因参数的数量而阻塞。


我们在找文件做家务。

找到。-exec echo {} \;命令运行了一夜,最后没有结果。

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

希望这能有所帮助。


之间的差别;(分号)或+(加号)是参数传入find的-exec/-execdir参数的方式。例如:

using ; will execute multiple commands (separately for each argument), Example: $ find /etc/rc* -exec echo Arg: {} ';' Arg: /etc/rc.common Arg: /etc/rc.common~previous Arg: /etc/rc.local Arg: /etc/rc.netboot All following arguments to find are taken to be arguments to the command. The string {} is replaced by the current file name being processed. using + will execute the least possible commands (as the arguments are combined together). It's very similar to how xargs command works, so it will use as many arguments per command as possible to avoid exceeding the maximum limit of arguments per line. Example: $ find /etc/rc* -exec echo Arg: {} '+' Arg: /etc/rc.common /etc/rc.common~previous /etc/rc.local /etc/rc.netboot The command line is built by appending each selected file name at the end. Only one instance of {} is allowed within the command.

参见:

人找到 在find at SO中使用分号(;)vs +(+)和exec 简单的unix命令,{}和\;对于在SO 在find的-exec命令中{}+是什么意思?在Unix