AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / unix / 问题 / 474519
Accepted
joker
joker
Asked: 2018-10-11 04:41:43 +0800 CST2018-10-11 04:41:43 +0800 CST 2018-10-11 04:41:43 +0800 CST

查找和符号链接

  • 772

我正在浏览 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。

是什么赋予了?

我看过这篇文章,说文件名不是文件属性。这是我无法真正理解的事情。

linux command-line
  • 1 1 个回答
  • 1729 Views

1 个回答

  • Voted
  1. Best Answer
    Kamil Maciorowski
    2020-03-07T17:53:30+08:002020-03-07T17:53:30+08:00

    Gnufind文档在术语上不像POSIX文档那样严格。后者阐明了这一点,我将参考它。它没有定义-iname,所以我将专注于-name. 我假设-iname被设计为类似-name,仅不区分大小写。因此,我希望所有-name与 case 无关的属性也适用-iname。

    这些是 POSIX 文档的相关部分:

    find [-H|-L] path... [operand_expression...]
    该实用程序将从, […]find指定的每个文件递归地降低目录层次结构。path每个path操作数都应按原样进行评估,包括所有尾随 <slash> 字符;层次结构中遇到的其他文件的所有路径名应由当前路径操作数的串联、如果当前路径操作数不是以 1 结尾的 <slash> 以及相对于路径操作数的文件名组成。相对部分不应包含点或点-点组件,不包含尾随 <slash> 字符,并且路径名组件之间仅包含单个 <slash> 字符。

    -name pattern
    如果当前路径名的基名pattern使用模式匹配表示法匹配,则主节点应评估为真 […]

    -print
    [...] 它将导致当前路径名被写入标准输出。

    和定义:

    Basename
    对于包含至少一个文件名的路径名:路径名中的最终文件名或唯一文件名。[…]

    文件名
    用于命名文件的字节序列 […]。组成名称的字节不应包含 <NUL> 或 <slash> 字符。[…] 文件名有时被称为“路径名组件”。[…]

    路径名
    用于标识文件的字符串。[…] 它有可选的开头 <slash> 字符,后跟零个或多个由 <slash> 字符分隔的文件名。

    所以-name对当前路径名中的最终文件名感兴趣;当前路径名是一个字符串,用于标识当前文件。被谁使用?在这种情况下,由find. 从概念上讲,路径名可能与文件系统中的名称无关。如果find使用某个字符串来标识文件,则该字符串称为“路径名”并-name使用它。

    调用find . -print或find -L . -print。您将看到此特定调用使用的所有路径名find。它们的最终文件名是-name您使用-name.


    在您使用 and 的示例中main-file,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-fileand ./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工作原理的示例:

    1. cd /etc && find . -name . 2>/dev/null

      尽管.事实上它的“真实”(特定的,在文件系统中)名称是etc. .尽管在某些情况下任何目录都可能存在,但它不会找到子目录。

    2. cd /etc && find . -name etc 2>/dev/null

      它既没有etc也没有.。

    3. 创建一个空的 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-maxdepthmain-filesl-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只会打印

    ./main-file
    

    -type与文件一起使用,因此find . -type f将打印一个路径名:

    ./main-file
    

    并将find -L . -type f打印两个路径名:

    ./main-file
    ./sl-file
    
    • 2

相关问题

  • 使用键盘快捷键启动/停止 systemd 服务 [关闭]

  • 需要一些系统调用

  • 没有服务器的命令行 pub/sub?

  • astyle 不会更改源文件格式

  • 通过标签将根文件系统传递给linux内核

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    如何将 GPG 私钥和公钥导出到文件

    • 4 个回答
  • Marko Smith

    ssh 无法协商:“找不到匹配的密码”,正在拒绝 cbc

    • 4 个回答
  • Marko Smith

    我们如何运行存储在变量中的命令?

    • 5 个回答
  • Marko Smith

    如何配置 systemd-resolved 和 systemd-networkd 以使用本地 DNS 服务器来解析本地域和远程 DNS 服务器来解析远程域?

    • 3 个回答
  • Marko Smith

    如何卸载内核模块“nvidia-drm”?

    • 13 个回答
  • Marko Smith

    dist-upgrade 后 Kali Linux 中的 apt-get update 错误 [重复]

    • 2 个回答
  • Marko Smith

    如何从 systemctl 服务日志中查看最新的 x 行

    • 5 个回答
  • Marko Smith

    Nano - 跳转到文件末尾

    • 8 个回答
  • Marko Smith

    grub 错误:你需要先加载内核

    • 4 个回答
  • Marko Smith

    如何下载软件包而不是使用 apt-get 命令安装它?

    • 7 个回答
  • Martin Hope
    rocky 如何将 GPG 私钥和公钥导出到文件 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Wong Jia Hau ssh-add 返回:“连接代理时出错:没有这样的文件或目录” 2018-08-24 23:28:13 +0800 CST
  • Martin Hope
    Evan Carroll systemctl 状态显示:“状态:降级” 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim 我们如何运行存储在变量中的命令? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S 为什么 /dev/null 是一个文件?为什么它的功能不作为一个简单的程序来实现? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 如何从 systemctl 服务日志中查看最新的 x 行 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - 跳转到文件末尾 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla 为什么真假这么大? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis 在一个巨大的(70GB)、一行、文本文件中替换字符串 2017-12-30 06:58:33 +0800 CST
  • Martin Hope
    Bagas Sanjaya 为什么 Linux 使用 LF 作为换行符? 2017-12-20 05:48:21 +0800 CST

热门标签

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve