是`ls -f | grep -c .` 使用 POSIX / Unix 系统(大数据)时计算目录中文件的最快方法?
Is `ls -f | grep -c .` the fastest way to count files in directory, when using POSIX / Unix system (Big Data)?
我曾经这样做 ls path-to-whatever| wc -l
,直到我发现它实际上消耗了大量内存。然后我移动到 find path-to-whatever -name "*" | wc -l
,它似乎消耗了大量的内存,无论你有多少文件。
然后我了解到,由于对结果进行排序,ls 的运行速度很慢且内存效率较低。通过使用ls -f | grep -c .
,一个人会得到非常快的结果;唯一的问题是文件名中可能包含 "line breaks"。但是,对于大多数用例来说,这是一个非常小的问题。
这是统计文件的最快方法吗?
编辑/可能的答案:似乎在涉及大数据时,据报道某些版本的 ls、find 等挂起超过 800 万个文件(尽管需要确认)。为了成功处理非常大的文件数(我的猜测是 > 22 亿),应该使用 getdents64 系统调用而不是 getdents,这可以用大多数支持 POSIX 标准的编程语言来完成。某些文件系统可能会提供更快的非POSIX 文件计数方法。
一种方法是使用readdir
并计算条目数(在一个目录中)。下面我正在计算常规文件并使用 d_type==DT_REG
,它可用于有限的操作系统和文件系统(man readdir
并参见注释),但您可以只注释掉该行并计算所有目录条目:
#include <stdio.h>
#include <dirent.h>
int main (int argc, char *argv[]) {
struct dirent *entry;
DIR *dirp;
long long c; // 64 bit
if(argc<=1) // require dir
return 1;
dirp = opendir (argv[1]);
if (dirp == NULL) { // dir not found
return 2;
}
while ((entry = readdir(dirp)) != NULL) {
if(entry->d_type==DT_REG)
c++;
// printf ("%s\n", entry->d_name); // for outputing filenames
}
printf ("%lli\n", c);
closedir (dirp);
return 0;
}
遵守 运行:
$ gcc code.c
$ ./a.out ~
254
(我需要清理我的主目录:)
编辑:
我将 1000000 个文件放入一个目录,运行 快速比较(最佳用户+系统,共 5 个):
$ time ls -f | grep -c .
1000005
real 0m1.771s
user 0m0.656s
sys 0m1.244s
$ time ls -f | wc -l
1000005
real 0m1.733s
user 0m0.520s
sys 0m1.248s
$ time ../a.out .
1000003
real 0m0.474s
user 0m0.048s
sys 0m0.424s
编辑 2:
根据评论中的要求:
$ time ./a.out testdir | wc -l
1000004
real 0m0.567s
user 0m0.124s
sys 0m0.468s
我曾经这样做 ls path-to-whatever| wc -l
,直到我发现它实际上消耗了大量内存。然后我移动到 find path-to-whatever -name "*" | wc -l
,它似乎消耗了大量的内存,无论你有多少文件。
然后我了解到,由于对结果进行排序,ls 的运行速度很慢且内存效率较低。通过使用ls -f | grep -c .
,一个人会得到非常快的结果;唯一的问题是文件名中可能包含 "line breaks"。但是,对于大多数用例来说,这是一个非常小的问题。
这是统计文件的最快方法吗?
编辑/可能的答案:似乎在涉及大数据时,据报道某些版本的 ls、find 等挂起超过 800 万个文件(尽管需要确认)。为了成功处理非常大的文件数(我的猜测是 > 22 亿),应该使用 getdents64 系统调用而不是 getdents,这可以用大多数支持 POSIX 标准的编程语言来完成。某些文件系统可能会提供更快的非POSIX 文件计数方法。
一种方法是使用readdir
并计算条目数(在一个目录中)。下面我正在计算常规文件并使用 d_type==DT_REG
,它可用于有限的操作系统和文件系统(man readdir
并参见注释),但您可以只注释掉该行并计算所有目录条目:
#include <stdio.h>
#include <dirent.h>
int main (int argc, char *argv[]) {
struct dirent *entry;
DIR *dirp;
long long c; // 64 bit
if(argc<=1) // require dir
return 1;
dirp = opendir (argv[1]);
if (dirp == NULL) { // dir not found
return 2;
}
while ((entry = readdir(dirp)) != NULL) {
if(entry->d_type==DT_REG)
c++;
// printf ("%s\n", entry->d_name); // for outputing filenames
}
printf ("%lli\n", c);
closedir (dirp);
return 0;
}
遵守 运行:
$ gcc code.c
$ ./a.out ~
254
(我需要清理我的主目录:)
编辑:
我将 1000000 个文件放入一个目录,运行 快速比较(最佳用户+系统,共 5 个):
$ time ls -f | grep -c .
1000005
real 0m1.771s
user 0m0.656s
sys 0m1.244s
$ time ls -f | wc -l
1000005
real 0m1.733s
user 0m0.520s
sys 0m1.248s
$ time ../a.out .
1000003
real 0m0.474s
user 0m0.048s
sys 0m0.424s
编辑 2:
根据评论中的要求:
$ time ./a.out testdir | wc -l
1000004
real 0m0.567s
user 0m0.124s
sys 0m0.468s