我正在浏览 find 的文档以更好地利用命令用法。
我正在阅读说
GNU find 将以两种方式之一处理符号链接;首先,它可以为您取消引用链接 - 这意味着如果遇到符号链接,它会检查链接指向的文件,以查看它是否符合您指定的标准。其次,它可以检查链接本身,以防您正在寻找实际链接。如果符号链接指向的文件也在您使用 find 命令搜索的目录层次结构中,那么您可能看不出这两种选择之间有很大的区别。
默认情况下,find 在找到符号链接时会自行检查它们(如果稍后遇到链接到的文件,它也会检查)。
据我了解,如果我这样做:
find -L -iname "*foo*"
这将递归搜索当前目录,当它遇到符号链接时,它会跟随原始文件的链接。如果原始文件的名称为 pattern *foo*
,则报告前一个链接。
然而,情况似乎并非如此。我有
main-file
sl-file -> main-file
运行上面的命令find -L -iname "*main*"
报告
./main-file
我期待着
./main-file # because it matches the criterion
./sl-file # because the file points to matches the criterion
话虽如此,使用另一个测试就像-type
我所期望的那样工作。说我有这个:
main-file
dir/sl-file -> ../main-file
运行这个
find dir -type f
什么都不返回。但是这个
find -L dir -type f
报告dir/sl-file
。
是什么赋予了?
我看过这篇文章,说文件名不是文件属性。这是我无法真正理解的事情。
Gnu
find
文档在术语上不像POSIX文档那样严格。后者阐明了这一点,我将参考它。它没有定义-iname
,所以我将专注于-name
. 我假设-iname
被设计为类似-name
,仅不区分大小写。因此,我希望所有-name
与 case 无关的属性也适用-iname
。这些是 POSIX 文档的相关部分:
和定义:
所以
-name
对当前路径名中的最终文件名感兴趣;当前路径名是一个字符串,用于标识当前文件。被谁使用?在这种情况下,由find
. 从概念上讲,路径名可能与文件系统中的名称无关。如果find
使用某个字符串来标识文件,则该字符串称为“路径名”并-name
使用它。调用
find . -print
或find -L . -print
。您将看到此特定调用使用的所有路径名find
。它们的最终文件名是-name
您使用-name
.在您使用 and 的示例中
main-file
,sl-file
命令是find -L -iname "*main*"
. 最后有隐含-print
,您观察到的输出来自-print
. 你期望:但如果是这种情况,那就意味着
-print
给了你./main-file
and./sl-file
,所以这些是确切的路径名,所以main-file
和sl-file
是相应的基本名称-name
(或-iname
)处理。这不合适。这些基本名称中只有一个与您使用的模式匹配 (
*main*
)。这就是为什么你只得到一个结果。指定-name "*main*"
(或-iname "*main*"
)并期望./sl-file
出现等同于期望sl-file
匹配*main*
。期望出现
./main-file
两次是有道理的。前提是符号链接导致find
将第二个路径名从 更改./sl-file
为./main-file
。然后两个路径名都将匹配*main*
,并且都将打印为./main-file
. 这不会发生。如果您希望发生这种情况,请考虑
bar
指向/etc/fstab
并放置在/tmp/foo/
. 我们在foo
目录中。应该find -L .
打印什么(除了.
)?您似乎希望此路径名通过-name fstab
测试,因此基本名称必须是fstab
. 另一方面,根据规则,路径名必须以./
(因为.
是提供的路径)开头,并且不得包含点-点组件。没有可以使用的合理且有意义的路径名。怎么办?幸运的是,在这种情况下,该工具只打印./bar
. 这是路径名,它(作为字符串)与fstab
.很少有不使用符号链接但显示其
-name
工作原理的示例:尽管
.
事实上它的“真实”(特定的,在文件系统中)名称是etc
..
尽管在某些情况下任何目录都可能存在,但它不会找到子目录。它既没有
etc
也没有.
。创建一个空的 FAT32 文件系统并将其挂载
cd
到挂载点。文件系统不区分大小写,Linux 知道这一点。在文件系统中创建一个名为a
的文件。像这样进行实验:在这种情况下,该工具必须
a
在某个时候从文件系统中获取。在这种情况下,该工具使用
a
或A
取自其命令行参数。文件系统仅确认此类文件存在。文件系统(和操作系统)知道这个特定文件可以称为a
或A
。没有什么!这表明
-name
不关心文件系统对文件的了解。只有find
事务使用的路径名。在您的示例中有点类似:
-iname
不关心文件系统对符号链接及其目标的了解。只有find
事务使用的路径名。为了澄清和明确说明会发生什么,让我们使用以下目录结构回到您的示例:
find . -print
或find -L . -print
打印:这些是路径名,即用于标识三个文件的字符串 (目录也是一个文件)。字符串来自命令,另外两个是通过检查构建的(现在我指的是文件,而不是字符串),了解它是目录类型,决定我们是否应该下降(一般认为,如果支持),列出其内容:, .
find
.
.
-prune
-maxdepth
main-file
sl-file
请注意,字符串
/.sl-file
是在对其标识的文件执行任何操作之前构建的。要对文件做任何事情,find
需要字符串。但是
-name
或者-print
不对文件做任何事情,他们不需要它的数据或元数据。它们与路径名、字符串一起工作。当
-name "*main*"
为任何路径名评估时,相应的文件或整个文件系统是完全不相关的。唯一相关的是路径名,它是一个字符串;更具体地说,它的最后一个组成部分,即基本名称,也是一个字符串。对于任何给定的路径名
-name
,无论您是否使用过-L
,或者该文件是否首先是符号链接,或者它指向的位置,或者它是否没有损坏,都无关紧要。它适用于已知的字符串。另一方面,测试喜欢
-type
或-mtime
需要向文件系统查询由路径名标识的文件。字符串对他们来说是不够的。如果是符号链接,-L
则决定他们是查询符号链接的目标还是符号链接本身。尽管如此,如果-print
涉及,那么无论查询什么,它都会打印路径名。换句话说:
没有
-L
./main-file
字符串标识./main-file
文件类型f
./sl-file
字符串标识./sl-file
文件类型l
和
-L
./main-file
字符串标识./main-file
文件类型f
./sl-file
字符串还标识类型的./main-file
文件f
然后,您应该注意哪些测试或操作适用于路径名(字符串)以及哪些适用于文件。
-name
并-print
使用路径名,所以find . -name "*main*"
有或没有-L
只会打印-type
与文件一起使用,因此find . -type f
将打印一个路径名:并将
find -L . -type f
打印两个路径名: