我也很困惑为什么find
命令也会打印修剪后的目录,以及其他一些如何-prune
工作的复杂细节,但是我能够通过一些示例来弄清楚。
要运行以下示例,请创建以下目录和文件。
mkdir aa
mkdir bb
touch file1
touch aa/file1
touch bb/file3
要创建此结构:
$ tree
.
├── aa
│ └── file1
├── bb
│ └── file3
└── file1
现在使用find查找名为的目录aa
。没问题
$ find . -type d -name aa
./aa
查找除aa以外的所有目录,我们得到当前目录.
和./bb
,这也很有意义。
$ find . -type d ! -name aa
.
./bb
到目前为止,一切都很好,但是当使用时-prune
,find返回正在修剪的目录,这最初使我感到困惑,因为我期望它返回所有其他目录,而不是正在修剪的目录。
$ find . -type d -name aa -prune
./aa
解释了它返回被修剪目录的原因,而不是-prune
在Timo的答案所示的手册页部分中说明,而是在该EXPRESSIONS
部分中说明:
如果表达式包含比其他任何动作-prune
,
-print
是在该表达式为true的所有文件执行。
这意味着,由于表达式与aa
目录名匹配,因此表达式将求值为true并被打印,因为find -print
在整个命令的末尾隐式添加了a 。-print
但是,如果您有意-o -print
自己将操作添加到结尾,则不会添加:
find . -type d -name aa -prune -o -print
.
./file1
./bb
./bb/file3
在这里,find命令-print
不再添加隐式命令,因此aa
将不会打印正在修剪的目录()。
所以最后,如果我们增加一个条款,对于具有的文件名模式的文件搜索file*
后-o
,那么你必须把-print
在像这样的第二句话结束:
find . \( -type d -name aa -prune \) -o \( -type f -name 'file*' -print \)
./file1
./bb/file3
起作用的原因是相同的:如果您未-print
在第二个子句中放置a ,则由于除了该-prune
动作外没有其他动作,find将-print
在命令的THE END处自动添加一个,导致该-prune
子句打印修剪目录:
find . \( \( -type d -name aa -prune \) -o \( -type f -name 'file*' \) \) -print
./aa
./file1
./bb/file3
通常,您需要将-print
命令放在第二个子句中。如果像原始海报一样将其放置在中间,它将无法正常工作,因为被修剪的文件将立即打印出来,第二子句将没有机会选择想要的文件:
find . \( -type d -name aa -prune -o -print \) -o \( -type f -name 'file*' \)
.
./file1
./bb
./bb/file3
因此,很不幸,原始海报将放置-print
在错误的位置,从而使上面的命令错误。它可能适用于他的特定情况,但在一般情况下不起作用。
成千上万的人难以理解其-prune
工作原理。该find
手册页应以防止此命令的无止境的全球混乱更新。
-print
,否则隐含-print
适用于整个状态