如何优化此 Perl 文件查找?
How to optimize this Perl file find?
需求:获取输入目录下符合以下条件的目录数
- 目录可以有任何名称,除了 "DIR1"、"DIR2"、"DIR3" 等
- "DIR1"、"DIR2"、"DIR3"等里面的目录不用计算
- 只需要目录数,不需要文件数
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;
}
这段代码提供了所需的输出,但它花费了很多时间。
请提出改进此代码以减少所用时间的方法。
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
)。对子目录进行分组,使它们的子目录数量大致平衡,并且 运行 类似上面的内容在这些组中并行。增益将取决于您的硬件,但应该有一个很好的加速因子。
需求:获取输入目录下符合以下条件的目录数
- 目录可以有任何名称,除了 "DIR1"、"DIR2"、"DIR3" 等
- "DIR1"、"DIR2"、"DIR3"等里面的目录不用计算
- 只需要目录数,不需要文件数
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;
}
这段代码提供了所需的输出,但它花费了很多时间。
请提出改进此代码以减少所用时间的方法。
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
)。对子目录进行分组,使它们的子目录数量大致平衡,并且 运行 类似上面的内容在这些组中并行。增益将取决于您的硬件,但应该有一个很好的加速因子。