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。我不知道为什么会这样,因为它只是我的副本。
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。我不知道为什么会这样,因为它只是我的副本。