我浏览了 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
。
是什么赋予了?
我已经经历过这个帖子这说明文件名不是文件属性。这是我实在无法理解的事情。
答案1
Gnufind
文档在术语上并不像POSIX一。后者阐明了这一点,我将参考它。它没有定义-iname
,所以我将专注于-name
.我认为-iname
它的设计类似于-name
,只是不区分大小写。因此,我希望它的所有属性也-name
与适用的情况无关。-iname
这些是 POSIX 文档的相关部分:
find [-H|-L] path... [operand_expression...]
该find
实用程序应从path
[…] 指定的每个文件递归地降低目录层次结构。每个path
操作数应在提供时按原样进行评估,包括所有尾随 <slash> 字符;层次结构中遇到的其他文件的所有路径名应由当前路径操作数、<slash>(如果当前路径操作数不以 1 结尾)以及相对于路径操作数的文件名的串联组成。相对部分不应包含点或点-点组件,不应包含尾随 <slash> 字符,路径名组件之间仅应包含单个 <slash> 字符。
-name pattern
如果当前路径名的基本名pattern
使用模式匹配符号 [...]匹配,则主项应评估为 true
[...]它将导致当前路径名被写入标准输出。
和定义:
基本名称
对于至少包含一个文件名的路径名:路径名中的最后一个或唯一一个文件名。 […]
文件名
用于命名文件的字节序列 [...]。组成名称的字节不得包含 <NUL> 或 <slash> 字符。 [...] 文件名有时被称为“路径名组件”。 […]
路径名
用于标识文件的字符串。 [...] 它具有可选的开头 <slash> 字符,后跟零个或多个由 <slash> 字符分隔的文件名。
所以-name
对当前路径名中的最终文件名感兴趣;当前路径名是一个字符串,用于标识当前文件。被谁使用?在这种情况下,通过find
.从概念上讲,路径名可能与文件系统中的名称无关。如果find
使用某个字符串来标识文件,则该字符串称为“路径名”并-name
使用它。
调用find . -print
或find -L . -print
.您将看到此特定调用使用的所有路径名find
。如果-name
您使用-name
.
main-file
在您使用and 的示例中sl-file
,命令是find -L -iname "*main*"
。-print
最后有隐式,您观察到的输出来自-print
.您期望:
./main-file # because it matches the criterion ./sl-file # because the file points to matches the criterion
但如果是这种情况,则意味着-print
给了您./main-file
和./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
工作原理的示例:
cd /etc && find . -name . 2>/dev/null
尽管事实上
.
它的“真实”(特定的,在文件系统中)名称是etc
.尽管在某些情况下任何目录都可以存在,但它找不到子目录.
。cd /etc && find . -name etc 2>/dev/null
它既找不到
etc
也没有.
。创建一个空的 FAT32 文件系统并将其安装
cd
到安装点。文件系统不区分大小写,Linux 知道这一点。创建一个a
在文件系统中命名的文件。像这样进行实验:$ find . . ./a
a
在这种情况下,该工具必须在某个时刻从文件系统获取。$ find a a $ find A A
在这种情况下,该工具使用
a
或A
取自其命令行参数。文件系统仅确认此类文件存在。文件系统(和操作系统)知道这个特定文件可以称为a
或A
。$ find a -name A $ find A -name a
没有什么!这表明
-name
并不关心文件系统对文件的了解。只有所使用的路径名才find
重要。在您的示例中有些类似:
-iname
不关心文件系统对符号链接及其目标的了解。只有所使用的路径名才find
重要。
为了澄清并明确说明发生的情况,让我们回到具有以下目录结构的示例:
.
├── main-file
└── sl-file -> main-file
find . -print
或find -L . -print
打印:
.
./main-file
./sl-file
这些是路径名,即字符串 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*"
with 或 without-L
只会打印
./main-file
-type
适用于文件,因此find . -type f
将打印一个路径名:
./main-file
并将find -L . -type f
打印两个路径名:
./main-file
./sl-file