如何优化这个Perl文件查找?

时间:2017-05-16 07:22:51

标签: perl file-find

要求:获取输入目录下符合以下条件的目录数

  1. 目录可以有任何名称,除了" DIR1"," DIR2"," DIR3"等。
  2. 里面的目录" DIR1"," DIR2"," DIR3"不需要计算
  3. 需要单独的目录数,没有文件
  4. use strict;
    use File::Find;
    
    my ($inputdir) = @ARGV; 
    my (@branches, $branch, $directory, @directories); 
    my $count = 0; 
    
    find(\&wanted, $inputdir); 
        while ( defined($directory = shift @directories) ) {
              if (-d $directory){ 
                 next if ($directory =~ "DIR1" || $directory =~ "DIR2" || $directory =~ "DIR3"); 
                         push @branches, $directory; 
                         $count++; 
              }
        } 
    
    print "Total number of directories: $count \n"; 
    
    sub wanted{
        push @directories, $File::Find::name;
        return @directories; 
    }
    

    这段代码提供了所需的输出,但需要花费很多时间。

    请建议减少改进此代码所需时间的方法。

1 个答案:

答案 0 :(得分:3)

File::Find::Rule可以完全跳过整个分支

use warnings;
use strict;

use File::Find::Rule;

my $start_dir = shift || '.';

my $re_skip = qr/DIR(?:1|2|3)/;

my $ok   = File::Find::Rule->directory;  # add selection rules as needed
my $skip = File::Find::Rule->directory
    ->name(qr/$re_skip/)
    ->prune
    ->discard; 

my @dirs = File::Find::Rule -> any($skip, $ok) -> in($start_dir); 

print "Total: ", scalar @dirs, "\n";

这仍然需要花费一些时间来处理大型文件系统,但它会好得多。

在单行中,如果你需要的只是一个快速计数

perl -MFile::Find::Rule -wE'
    $ffr = File::Find::Rule; 
    $skip = $ffr->directory->name(qr/DIR(?:1|2|3)/)->prune->discard; 
    say scalar $ffr->any($skip, $ffr->directory)->in(".")'

我从脚本中整合了一些代码。

下一步是使用多线程执行(我在这里使用fork)。对子目录进行分组,使它们在子计数中大致平衡,并在这些组上并行运行类似上面的内容。增益取决于您的硬件,但应该有一个很好的加速因子。