在find中使用分号(;)vs +(+)和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
47581 次浏览

find有特殊的语法。你使用{},因为它们作为找到文件的路径名有意义,(大多数)shell不会解释它们。你需要反斜杠\;,因为分号对shell有意义,它会在find得到它之前吃掉它。因此,find希望在shell完成后,在传递给C程序的参数列表中看到的是

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

但是你需要在命令行上使用\;来通过shell获得参数的分号。

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

不能所做的就是使用

 -exec 'rm {} ;'

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

"-exec", "rm {};"

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

更新

区别在于

$ ls file1
$ ls file2

而且

$ ls file1 file2

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

man find:

-exec命令;

< p >执行命令;如果返回0 status则为True。所有后 要查找的参数被作为until命令的参数 遇到由';'组成的参数。字符串“{}” 被当前正在处理的文件名所取代 它出现在命令的参数中,而不仅仅是参数中 在那里它是单独的,就像在一些版本的find。两者都是 结构可能需要转义(使用'\')或引用to 用外壳保护它们不膨胀。参见例句 节中'-exec'选项的使用示例。< >强 . . . 该命令在起始目录下执行。有 使用-exec选项时不可避免的安全问题; 你应该使用-execdir选项来代替

-exec命令{}+

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

.开始目录

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

ls testdir1; ls testdir2

vs

ls testdir1 testdir2

在我的shell中执行上述操作反映了您的问题中的输出。

当你想要使用\+的例子

假设有两个文件,1.tmp2.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.tmpdiff 1.tmp 2.tmp之间的差值

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

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

file1
file2
file3

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

ls file1
ls file2
ls file3

但如果你使用一个加号(find . -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形参中。例如:

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

    例子:

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

    find的所有参数都被当作命令的参数。

    字符串{}将被当前正在处理的文件名替换。

    李< /引用> < / >
  • 使用+将执行尽可能少的命令(因为参数被组合在一起)。它与xargs命令的工作方式非常相似,因此它将在每个命令中使用尽可能多的参数,以避免超过每行参数的最大限制。

    例子:

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

    命令行是通过在末尾追加每个选定的文件名来构建的。

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

    李< /引用> < / >

参见: