为什么 find 有时与其命令行路径参数匹配?

为什么 find 有时与其命令行路径参数匹配?

在 Linux 上,

cd /tmp
mkdir foo; cd foo

现在,跑步

find . -name 'foo'

没有输出。而跑步时

find /tmp/foo -name 'foo'

给出的输出/tmp/foo对我来说没有意义。有人可以解释为什么吗?

答案1

find遍历指定的目录树,并计算找到的每个文件的给定表达式。遍历从给定的路径开始。以下是操作方式的摘要find . -name foo

  • 命令行上的第一个路径:.
    • 基本名称 ( .) 与模式匹配吗foo?不,所以什么也不做。
      碰巧这/tmp/foo是同一目录的另一个名称。但find不知道这一点(也不应该试图找出答案)。
    • 路径是目录吗?是的,所以遍历它。枚举 中的条目.,并对每个条目执行遍历过程。
      • 该目录是空的:除了.和之外,它不包含任何条目..,并且find不会递归遍历。这样工作就完成了。

find /tmp/foo

  • 命令行上的第一个路径:/tmp/foo
    • 基本名称 ( foo) 与模式匹配吗foo?是的,所以条件符合。
      • 没有与此条件关联的操作,因此执行默认操作,即打印路径。
    • 路径是目录吗?是的,所以遍历它。枚举 中的条目/tmp/foo,并对每个条目执行遍历过程。
      • 该目录是空的:除了.和之外,它不包含任何条目..,并且find不会递归遍历。这样工作就完成了。

碰巧./tmp/foo是同一个目录,但这不足以保证find两者具有相同的行为。该find命令有方法区分同一文件的路径;谓词-name就是其中之一。find /tmp/foo -name foo匹配起始目录及其下面的任何名为foo.find . -name .仅匹配起始目录(.在递归遍历期间永远找不到)。

答案2

在应用测试之前,命令行参数没有标准化。因此,结果根据所使用的路径而有所不同(如果涉及符号链接):

cd /tmp
mkdir foo
ln -s foo bar
find /tmp/foo -name foo
find /tmp/bar -name foo

在“你的情况”中,两个调用都会给出相同的结果,这可能(更)令人困惑。-mindepth 1如果您希望忽略起始点(可能是非 POSIX),则可以使用。

答案3

(gnu) find 显示在提供给命令的路径中找到的任何匹配项,因为它开始与命令行参数进行比较,从那里深入到目录结构(因此,-maxdepth 0将测试限制在基本级别或仅命令行参数,而-mindepth 1跳过命令行参数,如man find所解释的那样)。这就是为什么find /tmp/foo -name 'foo'即使目录本身为空也会产生一个匹配的原因。

find . -name 'foo'另一方面,不会产生任何结果,因为.(dot) 是一个特殊文件,其作用就像到同一 inode 的硬链接一样/tmp/foo- 它就像一个单独的(虽然特殊)文件名,而不是符号链接或受约束的表达式shell 的路径名扩展。因此,find 对给定示例中的命令行参数应用的第一个测试将不会显示任何匹配项,因为.确实与 中定义的名称模式不匹配-name 'foo'。也不会,/tmp/foo/.因为模式测试-name仅在路径的基本名称上执行(请参阅man find),这里又是.

虽然这种行为可能不是预期的,或者从用户的角度来看并不直观(是的,它一开始也让我感到困惑),但它并不构成错误,而是与手册和信息页面中描述的逻辑和功能相对应( gnu) 查找。

答案4

foo在您开始相对搜索的目录中没有指定的对象。

当使用绝对名称作为启动目录时gfind报告时,您的假设是有错误的,这是正确的。/tmp/foo

Gfind与标准有各种偏差,看来您找到了另一个。当您喜欢更符合标准的解决方案时,我建议sfind将其作为schilytools.

-name适用于目录搜索结果。您提到的两种情况都不会fooreaddir()操作中返回目录条目。

相关内容