列出AIX机器上的大目录中的文件

时间:2018-03-21 23:11:05

标签: java shell perl unix aix

我有一个包含大约300万个文件的目录。每天一次,我需要运行一个进程,创建一个单独的文件,其中包含该扩展名为.html的大型目录中的文件名。通常,在那里的300万个文件中,500,000个将具有.html扩展名。我使用以下内容:

find dirname -name "*.html"

但是,它会在完成前运行大约3个小时。有更快的方法吗?

更新:我用Perl和Java做了一些测试。使用Perl获取此目录的内容并创建.html文件我尝试了以下(注意时间):

my @files = </$dirname/*.html>  # 45 minutes

当我使用Java尝试此操作时:

    final File[] files = dirname.listFiles(new FilenameFilter() {
                @Override
                public boolean accept(File dir, String name) {
                    return name.endsWith(".html");
                }
            }); 

与Perl或我能想到的任何Unix命令相比,Java如何在3分钟内完成此操作?

3 个答案:

答案 0 :(得分:2)

默认文件glob()对文件列表进行排序;这就是为什么需要很长时间。

my @files = </$dirname/*.html>  # 45 minutes

尝试直接阅读目录:

my @files = ();
opendir my $dh, $dirname or die "could not open $dirname: $!\n";
while( my $file = readdir $dh ){
    push @files, $file if $file =~ /\.html$/;
}
closedir $dh or die "could not close $dirname: $!\n";

答案 1 :(得分:1)

你应该使用&#34; getdents&#34;取代ls / find

ls和几乎所有其他列出目录的方法(包括python os.listdir,find。)都依赖于libc readdir()。但是readdir()一次只能读取32K的目录条目,这意味着如果你在同一目录中有很多文件(即500M的目录条目),那么读取所有目录条目将花费很长的时间。 ,特别是在慢速磁盘上。对于包含大量文件的目录,您需要比依赖readdir()的工具更深入地挖掘。您需要直接使用getdents()系统调用,而不是libc中的辅助方法。

您可以使用here中的getdents()找到C代码列出文件:

为了快速列出目录中的所有文件,您需要进行两项修改。

首先,将缓冲区大小从X增加到5兆字节。

#define BUF_SIZE 1024*1024*5

然后修改主循环,在那里打印出有关目录中每个文件的信息,以跳过带有inode == 0的条目。我这样做是通过添加

if (dp->d_ino != 0) printf(...);

在我的情况下,我也只关心目录中的文件名,所以我也重写了printf()语句只打印文件名。

if(d->d_ino) printf("%sn ", (char *) d->d_name);

编译它(它不需要任何外部库,所以它非常简单)

gcc listdir.c -o listdir

现在运行

./listdir [directory with insane number of files]

答案 2 :(得分:0)

你可以使用下面的ls

\ls -U

-U不排序;按目录顺序列出条目