我是Perl的新手。
我想以递归方式搜索包含多个子文件夹,子子文件夹和大量文件的大型目录树中的pdf
文件。
我正在使用File::Find::Rule
来实现这一目标。但是,性能影响巨大。
该脚本需要花费大量时间进行搜索。
来自我的Perl脚本的片段:
@folders = File::Find::Rule -> file -> name('*.[pP][dD][fF]') -> in($folderPath);
有没有其他方法可以在不影响性能的情况下实现这一目标?
任何帮助都将受到高度赞赏。
答案 0 :(得分: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。
答案 1 :(得分:1)
您可以尝试使用ag
代替:
my $cmd = 'ag -g "\.[pP][dD][fF]$" ' . $folderPath;
chomp(my @files = qx/$cmd/);
答案 2 :(得分: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;
}