计算目录中大量文件的最快/最简单方法是什么(在Linux中)?

时间:2011-05-21 16:31:15

标签: python linux ls directory-listing

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

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

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

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

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

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

7 个答案:

答案 0 :(得分:6)

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

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

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

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

答案 1 :(得分:3)

给定目录中的文件总数

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

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

find . -type f | wc -l

有关详细信息,请访问终端并执行man find

答案 2 :(得分: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)))

答案 3 :(得分:1)

我认为ls在显示第一行之前花费了大部分时间,因为它必须对条目进行排序,因此ls -U应该更快地显示第一行(尽管它可能不是那么多总计更好。)

答案 4 :(得分:1)

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


#include <dirent.h>
#include <stdio.h>
#include <stdlib.h>

int
main( int argc, char **argv )
{
    DIR *d;
    struct dirent *f;
    int count = 0;
    char *path = argv[ 1 ];

    if( path == NULL ) {
        fprintf( stderr, "usage: %s path", argv[ 0 ]);
        exit( EXIT_FAILURE );
    }
    d = opendir( path );
    if( d == NULL ) { perror( path );exit( EXIT_FAILURE ); }
    while( ( f = readdir( d ) ) != NULL ) {
        if( f->d_name[ 0 ] != '.'  &&  f->d_type == DT_REG )
            count += 1;
    }
    printf( "%d\n", count );
    return EXIT_SUCCESS;
}

答案 5 :(得分:0)

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

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

答案 6 :(得分:0)

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

ls -U {dir} | wc -l

需要6.4secs,其中32k文件(32k = FAT32上的max files / dir) 从python做起

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

只需0.874秒(!)看不到Python中的任何其他东西比这更快。