我有一些目录,包含大量文件。每当我尝试访问其中的文件列表时,我都无法做到这一点,或者有明显的延迟。我试图在Linux上的命令行中使用ls
命令,而我的托管服务提供商的网络界面也没有帮助。
问题是,当我做ls
时,甚至开始显示某些内容需要花费大量时间。因此,ls | wc -l
也无济于事。
经过一番研究后,我想出了这段代码(在这个例子中,它计算了某些服务器上新电子邮件的数量):
print sum([len(files) for (root, dirs, files) in walk('/home/myname/Maildir/new')])
上面的代码是用Python编写的。我使用了Python的命令行工具,它运行得非常快(立即返回结果)。
我对以下问题的答案感兴趣:是否可以更快地计算目录(没有子目录)中的文件?最快的方法是什么?
答案 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中的任何其他东西比这更快。