当使用POSIX/Unix系统(大数据)时,`ls-f | grep-c.`是计算目录中文件数的最快方法吗?

当使用POSIX/Unix系统(大数据)时,`ls-f | grep-c.`是计算目录中文件数的最快方法吗?,unix,filesystems,bigdata,Unix,Filesystems,Bigdata,我过去常常使用ls路径访问任何| wc-l,直到我发现它实际上消耗了大量内存。然后我转到查找到which-name“*”| wc-l的路径,这似乎消耗了大量内存,而不管您有多少文件 然后我了解到,由于对结果进行排序,ls通常速度较慢,内存效率较低。使用ls-f | grep-c.,可以得到非常快的结果;唯一的问题是文件名中可能有“换行符”。然而,对于大多数用例来说,这是一个非常小的问题 这是计数文件的最快方法吗 编辑/可能的答案:似乎在大数据方面,有报道称ls、find等的某些版本挂起了超过80

我过去常常使用
ls路径访问任何| wc-l
,直到我发现它实际上消耗了大量内存。然后我转到
查找到which-name“*”| wc-l
的路径,这似乎消耗了大量内存,而不管您有多少文件

然后我了解到,由于对结果进行排序,ls通常速度较慢,内存效率较低。使用
ls-f | grep-c.
,可以得到非常快的结果;唯一的问题是文件名中可能有“换行符”。然而,对于大多数用例来说,这是一个非常小的问题

这是计数文件的最快方法吗


编辑/可能的答案:似乎在大数据方面,有报道称ls、find等的某些版本挂起了超过800万个文件(不过需要确认)。为了成功地处理非常大的文件计数(我猜>22亿),应该使用getdents64系统调用,而不是getdents,这可以通过支持POSIX标准的大多数编程语言来完成。一些文件系统可能提供更快的非POSIX方法来计算文件。

一种方法是使用
readdir
并计算条目(在一个目录中)。下面我计算常规文件的数量,并使用
d_type==DT_REG
,该文件可用于有限的OSs和FSs(
man readdir
,请参见注释),但您可以只注释掉该行并计算所有dir条目:

#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;
}
(我需要打扫我的房间)

编辑:

我将1000000个文件放入一个目录中,并运行一个快速比较(显示了5个最佳用户+系统):

编辑2

按照评论中的要求:

$ time ./a.out testdir | wc -l
1000004

real    0m0.567s
user    0m0.124s
sys     0m0.468s

计算目录中的文件数,非递归?大约,我们在谈论多少个文件?可能是@James Brown的复制品:我们在谈论数百万或数十亿个文件;实际上,人们对不同方案的理论计算复杂性更感兴趣。我还对文件系统/操作系统级别的答案感兴趣,而不仅仅是“完成任务”ls-U1似乎是一个非常好的选择。但是,它不是POSIX标准;不过,我对Unix解决方案很满意。编辑了这个问题,因为我已经找到了令人满意的答案;然而,我仍然对这个问题的理论方面感兴趣。非常感谢你的回答!您是否也可以运行一个与ls-f(启用文本输出和
time../a.out | wc-l
)相同的测试,以便这两种方法在功能上相同?添加了结果。Ole hyvä。
$ 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
$ time ./a.out testdir | wc -l
1000004

real    0m0.567s
user    0m0.124s
sys     0m0.468s