在Linux上快速查找一个目录中文件数量的方法

3
我正在寻找一种快速的方法来查找Linux上目录中文件的数量。任何以目录中的文件数量为线性时间的解决方案都不可接受(例如“ls | wc -l”等),因为它需要极长的时间(目录中有数千万或数亿个文件)。我确信目录中的文件数量必须存储在文件系统结构(例如inode)中作为存储目录条目的数据结构的一部分-如何获取该数字?编辑:文件系统是ext3。如果没有便携式方法可以做到这一点,则愿意执行特定于ext3的操作。

几乎重复:https://dev59.com/43M_5IYBdhLWcg3wUxZB,讨论如何加速标准的ls | wc-l。 - Mark
我认为这个数字并不是以纯数字的形式存储在某个地方(尽管我没有阅读规范)。简单来说,这会减慢文件系统的速度,你需要同步touch/unlink/mv等操作才能得到可靠的结果,在发生崩溃的情况下,数字可能会损坏,因此你需要在某个时候重新计算文件数。此外,至少在我的Ubuntu Nautilus中,目录中对象的数量是由它自己缓存的,如果底层文件系统中有一个数字,我认为它不会这样做。 - Ivo Wetzel
我在想...目录条目的大小(即在父目录中执行ls -l时看到的目录大小)是否与条目数量有关?对于这个目录来说,它似乎比通常要大。 - HighCommander4
目录的大小可以与其中曾经存储的最大文件数量相关联。目录本质上是一个包含指向实际文件的稀疏数组指针的普通文件。 - Dummy00001
“数千万甚至上亿个文件”是一种病态情况。一个目录中大量的文件确实会影响性能;这就是为什么/usr/share/terminfo为每个条目使用的初始字符都有一个子目录,以便可以更像树形结构遍历,以保持文件计数较少。有些文件系统更类似于数据库,其中计数归结为单个快速查询,但这些在Unix世界中并不常见(如果它们存在的话,我不知道)。 - Stephen P
5个回答

6
数据结构为什么需要包含数字?一个树不需要在O(1)时间内知道它的大小,除非这是一个要求(并且提供这个要求可能需要更多的锁定和可能出现性能瓶颈)。
通过树我并不是指包括子目录内容,而是指具有-maxdepth 1的文件 - 假设它们并没有真正存储为列表...
编辑:ext2将它们存储为链接列表。
现代ext3实现了哈希B树。
话虽如此,/bin/ls做了很多事情,实际上扫描了所有的inode。编写您自己的C程序或使用opendir()和readdir()脚本。
来自这里
#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;
}

2
实际上,只要您不传递其他选项,如“--color”或“-F”,ls -a不会从文件系统中读取比您的程序更多的数据。请注意,ls -a或您的程序返回的计数包括“.”和“..”条目(因此空目录有两个条目)。在Linux上,ls -A跳过“.”和“..”。 - Gilles 'SO- stop being evil'
它从哪里获取文件名呢?我似乎记得需要读取索引节点才能获取它们。但是已经很久了,你可能是对的。 - Marco Mariani
2
@Gilles 是正确的 - 文件名在目录中,而不是文件 inode 中(毕竟,单个文件 inode 可以有多个名称)。文件名对你编写的程序可用,在 d->d_name 中。 - caf

2
您可以使用inotify来跟踪和记录监视目录中的文件创建和删除事件。它会分配维护文件计数所需的总时间,并使您能够即时检索当前文件计数。

1

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

我认为您别无选择,只能浏览整个目录中的文件列表。find命令可能比ls命令快,也可能慢一些。

这是一个例子,说明即使使用B树实现目录,大目录仍然是问题。


0

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


我不需要一种可移植的方式,我只需要一种方式。如果有关系的话,文件系统是ext3。 - HighCommander4

0

如果你愿意费些周折,你可以将每个目录放在不同的文件系统中,使用配额,并使用“repquota”命令获取信息。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接