GNU find -not 和 GNU find -prune -o -print 之间的区别

GNU find -not 和 GNU find -prune -o -print 之间的区别

这个关于在 vim 中打开除 [条件] 之外的所有文件的答案:

https://unix.stackexchange.com/a/149356/98426

给出了类似的答案:

find . \( -name '.?*' -prune \) -o -type f -print

(我修改了答案,因为我的问题与 vim 无关)

否定条件位于转义括号中。但是,在我的测试文件中,以下内容

find . -type f -not -name '^.*'

产生相同的结果,但更容易阅读和编写。 -not 方法与 -prune 方法一样,会修剪以 . (点)。我想知道 -not 和 -prune -o -print 方法会产生不同结果的边缘情况是什么。

Findutils 的信息页面内容如下:

-不是表达式: 如果 expr 为假则为真

-prune:如果文件是目录,则不要进入该目录。 (并进一步解释需要 -o -print 来实际排除顶级匹配目录)

它们似乎很难以这种方式进行比较,因为 -not 是一个测试,而 -prune 是一个操作,但对我来说,它们是可以互换的(只要 -o -print 在 -prune 之后)

答案1

首先,请注意这-not是一个 GNU 扩展,相当于标准!运算符。相比之下,它几乎没有任何优势!

谓词-prune始终评估为真的并影响目录树的行走方式find。如果运行的文件-prune属于以下类型目录(可能在使用-L//进行符号链接解析后确定),然后将不会下降到其中。-H-followfind

所以-name 'pattern' -prune( 的缩写-name 'pattern' -a -prune)与相同,-name 'pattern'只是名称匹配的目录pattern将是修剪过的,那就find不会降临到他们身上。

-name '.?*'.匹配名称以 1开头的文件特点(其定义取决于当前语言环境)后跟 0 个或多个人物。因此,实际上,它匹配.后跟一个或多个字符(以免修剪.起始目录)。

因此,这会匹配隐藏文件,但需要注意的是,它仅匹配那些名称也完全由其组成的文件人物,即当前语言环境中的有效文本(至少对于 GNU 实现而言)。

所以在这里,

find . \( -name '.?*' -a -prune \) -o -type f -a -print

哪个是相同的

find . -name '.?*' -prune -o -type f -print

因为 AND(-a隐含)优先于 OR(-o)。

查找以下文件常规的(没有符号链接、目录、fifo、设备...)并且不隐藏并且不在隐藏目录中(假设所有文件路径都是语言环境中的有效文本)。

find . -type f -not -name '^.*'

或其标准等效项:

find . -type f ! -name '^.*'

会找到名称不以^..

find . -type f ! -name '.*'

会找到名称不以 开头的常规文件.,但仍会报告隐藏目录中的文件。

find . -type f ! -path '*/.*'

会忽略隐藏文件和隐藏目录中的文件,但find仍然会下降到隐藏目录(任何级别深度),只是为了跳过其中的所有文件,因此比使用-prune.

答案2

-prune中的谓词删除find搜索树的一个分支。因此,-prune 如果目录中没有隐藏名称的文件,那么在问题中的第一个命令中使用 as 只会给出与第二个命令相同的结果。

例子:

$ tree -a
.
|-- .hiddendir
|   `-- file
`-- dir
    `-- file

2 directories, 2 files
$ find . \( -name '.?*' -prune \) -o -type f -print
./dir/file
$ find . -type f ! -name '.*'
./dir/file
./.hiddendir/file

(我-name在这里更正了测试,因为您似乎使用了无意义的正则表达式,并且我用它!代替了非标准-not)。

正如您所看到的,由于名称.hiddendir与通配模式匹配.?*,因此使用第一个命令将其从搜索树中删除,并且file找不到其下面的文件。

在第二个命令中,.hiddendir目录没有从搜索树中删除,因此file可以找到其中的文件。

相关内容