【问题标题】:Why do directory listings contain the current (.) and parent (..) directory?为什么目录列表包含当前 (.) 和父 (..) 目录?
【发布时间】:2010-09-24 06:37:55
【问题描述】:

每当我使用 readdir 之类的函数列出目录的内容时,返回的文件名也包括“.”。和 ”..”。我怀疑这些只是文件系统中的普通链接,因此与实际文件无法区分,但我总是必须将它们过滤掉,因为它们不是我列出的目录中的实际对象。像 readdir 这样的函数是否有充分的理由包含它们?某些操作系统或文件系统是否包含更多或不同的虚拟文件名?除了与“。”进行字符串比较之外,还有更好的方法来过滤掉它们吗?和“..”?

更新:谢谢大家的回答。我想我一直认为像 ./ 和 ../ 这样的东西只是可以通过搜索和替换来处理的约定。我觉得让它们成为文件系统本身的一部分有点令人惊讶,尽管可能更有效和透明。

不过,还有一个问题:因为 .和 .. 是这些链接的任意名称,是否存在使用不同名称的文件系统?

【问题讨论】:

    标签: operating-system filesystems


    【解决方案1】:

    ... 实际上是文件系统中的硬链接。它们是必需的,以便您可以根据一些参考路径指定相对路径(考虑"../sibling/file.txt")。由于这些硬链接实际上存在于文件系统中,因此readdir 告诉您它们是有意义的。 (实际上,hard link 一词只是表示与实际引用的目录无法区分的名称:它们都指向文件系统中的同一个 inode)。

    如果您不想列出它们,最好的方法是只 strcmp 并忽略它们。

    【讨论】:

    • 嗯,这很奇怪
    【解决方案2】:

    最初它们是硬链接,文件系统代码中特殊情况的数量为 .和..是最小的。然而,并非所有现代文件系统都是如此。

    但是已经建立了约定,因此即使这两个目录条目实际上不存在的文件系统仍然通过诸如 readdir 之类的 API 报告它们的存在。现在改变它会破坏很多代码。

    【讨论】:

      【解决方案3】:

      我怀疑这些是 只是文件系统中的普通链接 因此无法区分 实际文件

      他们是。虽然您可能将文件系统视为“文件夹”“包含”文件夹的层次结构,但它实际上是一个双向链接树1,目录是节点,文件是叶子。因此,... 是访问当前节点的叶子和遍历树所需的链接,它们与所有其他链接相同。

      当你调用readdir时,你会得到所有你可以从当前节点直接去的地方。如果您不想列出您认为“向上”的地方,则必须自己整理它们。您应该为此编写一个小函数,可能称为readdir_down。我不知道readdir 列出目录的顺序,但也许你可以把前两个条目扔掉。

      1) 这是第一个近似值,也有可能使树实际上成为网络的“硬链接”。

      【讨论】:

        【解决方案4】:

        一个原因是没有它们就无法访问父目录。或者获取当前目录的句柄。

        没有它们,我们就无法做到:

        ./run_this
        

        确实,我们无法添加 '.'到 $PATH,这意味着我们永远无法执行不在路径中的文件。

        【讨论】:

        • 在 Windows 上,.似乎是 PATH 的一部分,这意味着您只需键入 run_this。习惯了这一点,我总是觉得在使用 Linux 时坚持使用 ./ 前缀有点烦人,尽管我理解它对安全性的价值。
        • 在今年早些时候向我解释之前,我并没有真正考虑过安全限制。讨厌的用户可能在她的目录中有一个名为 ls 的命令,管理员在导航到该目录时可以执行该命令,然后该命令可以允许用户额外访问。不好。
        【解决方案5】:

        这些是普通目录,它们是指向当前目录和上面目录的“硬链接”。它们存在于所有目录中(即使在根级别,... 完全相同)。

        使用ls时,可以过滤掉...,使用ls -A(注意大写-A)。

        当对所有点文件应用命令时,而不是...,我经常使用.??*,它只匹配名称为三个或更多字符的点文件。

        touch .??*
        

        请注意,此模式还排除任何其他以点开头且只有两个字符长的文件(例如 .x),但这些文件并不常见。

        当使用像readdir() 这样的程序文件列表时,我必须手动排除...。由于这两个文件应该在readdir() 返回的列表中排在第一位,因此您可以这样做:

        @files = readdir(DIR);
        for (1..2) { shift @files; } # get rid of . and ..
        # go on with your business
        

        【讨论】:

        • 这两行应该放在一个函数中。
        • 你怎么知道它们不是 in 函数? :-)
        • 奇怪的是,在 Windows 上,根目录 (c:\, d:\, ...) 不包含任何两个链接。虽然省略 .. 可能有些道理,但省略 .没有。
        • 比尔,将我的评论视为“是的,并且……”,而不是“是的,但是……”。
        • 文件系统根目录中的..是一种特殊情况,至少对于挂载在其他文件系统中的文件系统而言。例如。如果/home 有自己的文件系统,则路径 /home/.. 指回父文件系统,即使实际目录条目... 具有相同的inode
        【解决方案6】:

        报告它们是因为它们存储在目录列表中。这就是 unice 一直以来的工作方式。

        【讨论】:

          【解决方案7】:

          因为在类 Unix 操作系统上,目录列表命令包含这些命令,您可以使用它们在文件系统层次结构中上下移动。

          grep { not /^.{1,2}\z/ } readdir HANDLE 之类的东西应该适合你。

          【讨论】:

          • 实际上,grep 字符串应该是 /^\.{1,2}$/,因为句号需要转义。我可能会把它写成 /^\.\.?$/.
          【解决方案8】:

          目录扫描没有理由返回这些文件名。

          【讨论】:

          • 目录扫描应该返回这些文件名是有充分理由的。你还怎么写getcwd()?
          • 同意。没有 。并且..,您无法获得当前目录或父目录的句柄。
          • 不过,我不明白这个论点。我已经需要知道当前目录才能获得它的“。”首先进入...
          • Lemming,你不要因为你可以做 readdir(".") 给你当前目录。
          猜你喜欢
          • 2018-06-25
          • 1970-01-01
          • 2015-08-22
          • 2011-10-16
          • 1970-01-01
          • 2013-06-22
          • 1970-01-01
          • 2018-06-18
          • 1970-01-01
          相关资源
          最近更新 更多