2016-11-30 56 views
1

我是Perl新手。 我想在包含多个子文件夹,子子文件夹和大量文件的大型目录树中递归搜索pdf文件。 我正在使用File::Find::Rule来实现这一点。但是,性能影响是巨大的。 该脚本需要花费大量时间进行搜索。Perl:在大型目录结构中搜索pdf文件recursivley

从我的Perl脚本

段:

@folders = File::Find::Rule -> file -> name('*.[pP][dD][fF]') -> in($folderPath); 

是否有任何其他的方式来实现这一目标,而不会影响性能?

任何帮助将不胜感激。

+1

(非perl)命令如何比较查找start_dir -name *。[pP] [dD] [fF]“?那是否比你的Perl脚本更快? – PerlDuck

回答

1

你可以尝试使用ag代替:

my $cmd = 'ag -g "\.[pP][dD][fF]$" ' . $folderPath; 
chomp(my @files = qx/$cmd/); 
0

尝试子程序这递归搜索子目录。在我的例子中,你必须传递你的起始目录和一个数组(通过引用,即:\ @ name_of_array),这些数据将填充子目录。我希望它可以提高性能,但我不知道这一点

sub list_dirs 
{ 
    my ($dir, $dirs) = @_; 
    opendir(D, $dir) || die "cannot open directory $dir\n\n"; 
    my @tmp_dirs = readdir(D); 
    closedir(D); 
    foreach my $tmp_dir (@tmp_dirs) 
    { 
     if (-d "$dir/$tmp_dir") 
     { 
      next if ($tmp_dir eq ".."); 
      next if ($tmp_dir eq "."); 
      push @$dirs, "$dir/$tmp_dir"; 
      list_dirs("$dir/$tmp_dir", $dirs); 
     } 
    } 
    return $dirs; 
} 
2

你的问题很简单:与其看着,因为它遇到的每个候选文件,你都在等待File::Find::Rule建立一个列表,并将其返回您。这意味着您将一直等待,直到它查看了该树下的所有文件。而且,从冷启动和足够数量的文件开始,在显示结果之前需要很长时间。

相反,您可以使用底层的File::Find来检查遇到的每个文件。您可能还会发现有用的Path::Tiny's iterator

您不会更改访问树下每个文件所需的时间。但是,通过处理遇到的每个文件,您将1)减少程序的内存占用量,因为不必构建巨大的列表;和2)你将看到更快的结果。

像这样的事情让你开始:

#!/usr/bin/env perl 

use strict; 
use warnings; 

use File::HomeDir qw(my_documents); 
use Path::Tiny; 

my $it = path(my_documents)->iterator({ recurse => 1 }); 

while (my $path = $it->()) { 
    return $path->is_file and $path =~/[.] pdf \z/ix; 
    do_something_with_pdf($path); 
} 

sub do_something_with_pdf { 
    print $_[0]->canonpath, "\n"; 
} 

如果你不喜欢的File::Find::Rule规则部分,你可能更喜欢Path::Iterator::Rule。重要的规则是避免在开始处理之前等待构建可能非常大的列表。

但是,如果您只需要一个快速的方法来获取所有PDF文件的列表,就应该考虑使用The Silver Searcher