【问题标题】:What is the fastest / easiest way to count large number of files in a directory (in Linux)?计算目录中大量文件的最快/最简单方法是什么(在 Linux 中)?
【发布时间】:2011-08-30 07:02:18
【问题描述】:

我有一些目录,里面有大量文件。每次我尝试访问其中的文件列表时,我都无法做到这一点,或者出现了明显的延迟。我试图在 Linux 的命令行中使用 ls 命令,而我的托管服务提供商的 Web 界面也没有帮助。

问题是,当我只执行ls 时,甚至开始显示某些内容都需要大量时间。因此,ls | wc -l 也无济于事。

经过一些研究,我想出了这段代码(在这个例子中,它计算了某个服务器上新电子邮件的数量):

print sum([len(files) for (root, dirs, files) in walk('/home/myname/Maildir/new')])

以上代码是用 Python 编写的。我使用了 Python 的命令行工具,它运行得非常快(立即返回结果)。

我对以下问题的答案感兴趣:是否可以更快地计算目录中的文件(没有子目录)?最快的方法是什么?

【问题讨论】:

  • 要同时统计文件数和目录数吗?
  • @Rafe 没关系 - 我所说的目录没有子目录。因此,两种解决方案都与我相同。

标签: python linux ls directory-listing


【解决方案1】:

ls 为每个文件调用stat(2)。其他工具,如find(1) 和shell 通配符扩展,可能会避免此调用,只需执行readdir。一个可能有效的 shell 命令组合是 find dir -maxdepth 1|wc -l,但它会很乐意列出目录本身并错误计算任何包含换行符的文件名。

从 Python 中获取这些名称的直接方法是 os.listdir(directory)。与 os.walk 和 os.path.walk 不同,它不需要递归、检查文件类型或进行进一步的 Python 函数调用。

附录:似乎 ls 并不总是统计。至少在我的 GNU 系统上,当不请求更多信息(例如哪些名称是目录)时,它只能执行 getdents 调用。 getdents 是用于在 GNU/Linux 中实现 readdir 的底层系统调用。

补充 2:ls 输出结果之前延迟的一个原因是它进行了排序和制表。 ls -U1 可以避免这种情况。

【讨论】:

    【解决方案2】:

    给定目录中的文件总数

    find . -maxdepth 1 -type f | wc -l
    

    给定目录及其下所有子目录中的文件总数

    find . -type f | wc -l
    

    欲了解更多详情,请进入终端并执行man find

    【讨论】:

      【解决方案3】:

      这在 Python 中应该很快:

      from os import listdir
      from os.path import isfile, join
      directory = '/home/myname/Maildir/new'
      print sum(1 for entry in listdir(directory) if isfile(join(directory,entry)))
      

      【讨论】:

        【解决方案4】:

        我不确定速度,但如果你只想使用 shell 内置,这应该可以:

        #!/bin/sh
        COUNT=0;
        for file in /path/to/directory/*
        do
        COUNT=$(($COUNT+1));
        done
        echo $COUNT
        

        【讨论】:

          【解决方案5】:

          我认为ls 大部分时间都在显示第一行之前,因为它必须对条目进行排序,所以ls -U 应该更快地显示第一行(尽管总体上可能不会好得多) .

          【讨论】:

            【解决方案6】:

            最快的方法是避免解释语言的所有开销并编写一些直接解决您的问题的代码。这样做很难以便携的方式进行,但非常简单。目前我在 OS X 机器上,但是将以下内容转换为 Linux 应该非常简单。 (我选择忽略隐藏文件,只计算常规文件...根据需要进行修改或添加命令行开关以获得所需的功能。)

            #include #include #include 整数 主要(int argc,char **argv) { 目录 *d; 结构 dirent *f; 整数计数 = 0; 字符 *path = argv[ 1 ]; 如果(路径 == NULL){ fprintf(stderr, "用法: %s 路径", argv[ 0 ]); 退出(EXIT_FAILURE); } d = opendir(路径); if( d == NULL ) { perror( 路径 );exit( EXIT_FAILURE ); } 而( ( f = readdir( d ) ) != NULL ) { if( f->d_name[ 0 ] != '.' && f->d_type == DT_REG ) 计数 += 1; } printf("%d\n", 计数); 返回 EXIT_SUCCESS; }

            【讨论】:

            • 虽然我没有完全了解这段代码的去向,但即使是这一点 C 语言的复杂性也是一个警告信号。此外,检查 readdir(3) 的手册页显示 d_type 可以是任何东西的 DT_UNKNOWN,并且您甚至需要 _BSD_SOURCE 才能在 GNU 系统中使用它(其他 *nixes 可能根本没有它)。尽管有解释器,但更高的抽象级别可能会使 Python 成为更好的工具。
            • 问题是:“最快的方法是什么?” C 实现会在运行时速度上碾压 python。
            • 实际上最快/最简单。如果部署时间比 CPU 时间更重要(与运行时间不同),我不会感到惊讶。无论哪种方式,该作业都是 I/O 绑定的。没有争议 C 的运行效率更高,只是注意到写得好需要更多的工作。
            【解决方案7】:

            我的用例是一个 linux SBC (Banana Pi) 计算 FAT32 USB 记忆棒目录中的文件。 在 shell 中,做

            ls -U {dir} | wc -l
            

            需要 6.4 秒,其中有 32k 个文件(32k = FAT32 上的最大文件/目录) 从python做的

            t=time.time() ; print len(os.listdir(d)) ; print time.time()-t
            

            只需要 0.874 秒(!)在 Python 中没有比这更快的了。

            【讨论】:

              【解决方案8】:

              在 bash 中计算目录中文件的一种更短的方法:

              文件=(*) ;回声 ${#files[@]}

              我在 tmpfs 中生成了 10_000 个空文件;在我的机器上计算它们需要 0.03 秒,运行 ls | wc -l 只是稍微慢了一点(我在之前和之间刷新了缓存以防万一)

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 2017-10-26
                • 2011-05-15
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2013-10-24
                • 1970-01-01
                相关资源
                最近更新 更多