GNU find:默认操作何时适用?

GNU find: when does the default action apply?

Debian 8 的 find 命令的手册页说:

If the whole expression contains no actions other than -prune or -print, -print is performed on all files for which the whole expression is true.

那么为什么这些输出不同:

$ mkdir -p test/foo test/bar && cd test && touch foo/bar bar/foo
$ # Test 1
$ find . -name foo -type d -prune -o -name foo
./foo
./bar/foo
$ # Test 2
$ find . -name foo -type d -prune -o -name foo -print
./bar/foo

所以测试 1:表达式是否包含 "no actions other than -prune or -print?" 嗯,不包括剪枝,是的,该语句是正确的,没有任何操作。所以这些结果是预期的,因为对于 ./foo -o 选项之前的表达式 returns True,所以它被打印出来。

但是测试 2:表达式是否包含 "no actions other than -prune or -print?" 好吧,除了 prune 和 print 之外,是的,该语句再次为真,没有其他操作。所以我希望得到相同的结果。

但是我没听懂./foo。为什么?

好像手册页应该是:"If the whole expression contains no actions other than -prune or -print, -print is performed on all files for which the whole expression is true."

让我们看看这个命令:

find . -name foo -type d -prune -o -name foo

由于 -print 是默认操作,因此此操作将应用于整个表达式集,即 -name foo -type d -prune -o -name foo。所以和下面的一样:

find . \( -name foo -type d -prune -o -name foo \) -print

现在让我们看看这个命令:

find . -name foo -type d -prune -o -name foo -print

根据 man find expr1 expr2 的优先级高于 expr1 -o expr2。所以在上面的命令中,两个表达式与 OR 运算符组合:

  • -name foo -type d -prune
  • -name foo -print

因此,如果您想将 -print 应用于两者,请使用括号:

find . \( -name foo -type d -prune -o -name foo \) -print

但是 -prune -o RHS 意味着 RHS 只对那些没有被修剪的项目进行评估。

我们可以通过 运行 find-D tree-D opt:

检查我们是否正确
find -D opt -O0 . -name foo -type d -prune -o -name foo -print
...
 (  ( -name foo [0.1] -a [0.04] [need type] -type d [0.4]  ) -a [0.04] [call stat] [need type] -prune [1]  ) -o [0.14]  ( -name foo [0.1] -a [0.1] -print [1]  ) 
./bar/foo


find -D opt -O0 . -name foo -type d -prune -o -name foo
 (  (  ( -name foo [0.1] -a [0.04] [need type] -type d [0.4]  ) -a [0.04] [call stat] [need type] -prune [1]  ) -o [1] -name foo [0.1]  ) -a [0.14] -print [1] 
./foo
./bar/foo

正如我们所见,find 从我们显式放置 -print 的第一个表达式生成 (... -prune) -o (... -print)。它从我们省略 -print.

的第二个表达式生成 (...) -a -print

所以我认为 "the whole expression" 手册页是指 OPERATORS 部分中描述的表达式部分之一。

我要进行更简单的解释,手册页有误。它应该说

If the whole expression contains no actions other than -prune or -print, -print is performed on all files for which the whole expression is true.

它还应该包含对 -quit 的警告,这是一个操作,但它会导致 -find 立即退出。因此,即使为整个表达式添加了隐式 -print,它也从未真正执行过。

posix find man page 包含更清晰的解释,尽管它没有扩展的 gnu 版本那么多的操作。

If no expression is present, -print shall be used as the expression. Otherwise, if the given expression does not contain any of the primaries -exec, -ok, or -print, the given expression shall be effectively replaced by:

( given_expression ) -print

gnu 调用的操作中,posix 仅定义了 -exec-ok-print-prune。它没有任何扩展操作 -delete-ls 等...因此定义仅通过省略 -prune.[=41= 与更正后的 gnu 相匹配]

这里有一些使用所有 gnu find 动作的例子来证明这一点。对于所有考虑以下文件结构

$ tree
.
└── file

-删除

$ find -name file -delete
$

-执行命令;

$ find -name file -exec echo '-exec is an action so an implicit -print is not applied' \;
-exec is an action so an implicit -print is not applied
$

-execdir 命令{} +

$ find -name file -exec echo 'This should print the filename twice if an implicit -print is applied: ' {} +
This should print the filename twice if an implicit -print is applied:  ./file
$

-fls

$ find -name file -fls file
$

-fprint

$ find -name file -fprint file
$

-ls

$ find -name file -ls
1127767338    0 -rw-rw-r--   1 user   user          0 May  6 07:15 ./file
$

-ok 命令;

$ find -name file -ok echo '-ok is an action so an implicit -print is not applied' \;
< echo ... ./file > ? y
-ok is an action so an implicit -print is not applied
$

-okdir 命令;

$ find -name file -okdir echo '-okdir is an action so an implicit -print is not applied' \;
< echo ... ./file > ? y
-okdir is an action so an implicit -print is not applied
$

-打印

#./file would be printed twice if an implicit `-print was applied`
$ find -name file -print
./file
$

-print0

#./file would be printed twice if an implicit `-print was applied`
$ find -name file -print0
./file$

-printf

$ find -name file -printf 'Since -printf is an action the implicit -print is not applied\n'
Since -printf is an action the implicit -print is not applied
$

-修剪

$ find -name file -prune
./file
$

-退出

$ find -name file -quit
$ find -D opt -name file -quit
...
Optimized command line:
( -name file [0.1] -a [0.1] -quit [1]  ) -a [0.1] -print [1]

Check the GNU Findutils manual,上面写着

If the expression contains no actions other than ‘-prune’, ‘-print’ is performed on all files for which the entire expression is true.

显然,debian's manual 是错误的,因为它只是一个 GNU Find。我不知道为什么会这样,因为它只是我的副本。