【问题标题】:Fast way to find the number of files in one directory on Linux在Linux上查找一个目录中文件数量的快速方法
【发布时间】:2011-03-18 01:11:16
【问题描述】:

我正在寻找一种快速查找 Linux 目录中文件数量的方法。

任何在目录中的文件数量上花费线性时间的解决方案都是不可接受的(例如“ls | wc -l”和类似的东西),因为它会花费非常长的时间(有几十甚至几百目录中的数百万个文件)。

我确定目录中的文件数必须作为一个简单的数字存储在文件系统结构中的某个位置(可能是 inode?),作为用于存储目录条目的数据结构的一部分 - 我怎样才能得到这个号码?

编辑:文件系统是 ext3。如果没有可移植的方式来做到这一点,我愿意做一些特定于 ext3 的事情。

【问题讨论】:

  • 几乎重复:stackoverflow.com/questions/1427032/…,谈如何加速标准ls | wc-l
  • 我不认为这是以纯数字形式存储的。(虽然我没有阅读规范)。仅仅因为它会减慢 FS,您需要同步 touch/unlink/mv 等以获得可靠的结果,同样在崩溃的情况下,数字可能已损坏,因此您需要在某个时候重新计算文件.另外,至少在我的 Ubuntu Nautilus 上,它会自行缓存目录中的对象数量,如果底层 FS 中有一个数字,我认为它不会这样做。
  • 我想知道...目录条目的大小(即当您在其父目录中执行 ls -l 时看到的目录大小)与条目数有关吗?这个目录看起来确实比平时大。
  • 目录的大小可以与曾经存储在其中的最大文件数相关联。在某种程度上,目录是一个包含稀疏数组的普通文件,其中包含指向实际文件的指针。
  • “数以亿计的文件”是一个病态的案例。目录中的大量文件确实会影响性能;这就是为什么/usr/share/terminfo 为条目使用的每个初始字符都有一个子目录,因此它可以像树一样被遍历以保持文件倒计时。有些文件系统更类似于数据库,其中计数归结为单个快速查询,但这些在 Unix 世界中并不常见(如果它们存在,IDK)。

标签: linux file directory filesystems ext3


【解决方案1】:

为什么数据结构要包含数字?一棵树不需要知道它在 O(1) 中的大小,除非它是一个要求(并且提供这个,可能需要更多的锁定并且可能是性能瓶颈)

我所说的树不是指包含子目录内容,而是包含 -maxdepth 1 的文件——假设它们没有真正存储为列表..

编辑:ext2 将它们存储为链表。

现代 ext3 实现 hashed B-Trees

话虽如此,/bin/ls 的作用远不止计数,而是实际上扫描所有 inode。使用 opendir() 和 readdir() 编写您自己的 C 程序或脚本。

来自here

#include <stdio.h>
#include <sys/types.h>
#include <dirent.h>
int main()
{
        int count;
        struct DIR *d;
        if( (d = opendir(".")) != NULL)
        {
                for(count = 0;  readdir(d) != NULL; count++);
                closedir(d);
        }
        printf("\n %d", count);
        return 0;
}

【讨论】:

  • 实际上ls -a 不会从文件系统中读取比您的程序更多的数据,只要您不传递其他选项,例如--color-F。请注意ls -a 或您的程序返回的计数包括... 条目(因此空目录有两个条目)。在 Linux 上,ls -A 会跳过 ...
  • 它从哪里获得文件名?我似乎记得要获得它们需要阅读 inode。但已经很久了,你可能是对的。
  • @Gilles 是对的 - 文件名在目录中,而不是文件 inode(毕竟,单个文件 inode 可以有多个名称)。文件名可用于您编写的程序,d-&gt;d_name)。
【解决方案2】:

您可以使用 inotify 跟踪和记录受监视目录中的文件创建和取消链接事件。它将分配维护文件计数所需的总时间,并允许您即时检索当前文件计数。

【讨论】:

    【解决方案3】:

    目录的 inode 不存储其中的文件数量,因为通常不需要将文件计数与目录中的名称列表分开。目录 inode 的链接计数确实间接给出了子目录的数量(st_nlink 是子目录的数量加 2)。

    我认为您别无选择,只能通读目录中的整个文件列表。 find 可能会也可能不会比 ls 快。

    这是一个为什么大目录是个问题的例子,即使目录是使用 B-tree 实现的。

    【讨论】:

      【解决方案4】:

      没有可移植的方式来做到这一点。低级文件原语,即readdir,工作就好像它是一个线性列表。显然,这是一种抽象,一些文件系统可能会存储一个计数。但是,访问它本质上是特定于文件系统的。

      【讨论】:

      • 我不需要便携的方式。我只是需要一个方法。如果重要的话,文件系统是 ext3。
      【解决方案5】:

      如果您愿意跳过障碍,您可能会将每个目录都放在不同的文件系统中,使用配额,并使用“repquota”命令获取信息。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-08-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-10-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多