您可以使用 map() 内置函数创建一个以文件名作为键的哈希,并将值设置为 undef 或 1 或其他更有用的值:
perl -E 'map { $filehash{$_} = undef }
qx( find ./ -type f -maxdepth 3 2>/dev/null ) ;
say keys %filehash ;'
例如,您可以使用文件扩展名作为每个哈希键的值(从File::Basename 获取带有fileparse() 的扩展名):
perl -MFile::Basename -E '
map { chomp; $filehash{$_} = ( fileparse($_, qr/\..[^.]*$/))[2] }
qx( find ./ -type f -maxdepth 3 2>/dev/null ) ;
say "$_ has $filehash{$_} extension" for keys %filehash ;'
然后您可以使用以下内容进行过滤:
perl -MFile::Basename -E '
map { chomp; $files_ext{$_} = ( fileparse($_, qr/\..[^.]*$/))[2] }
qx( find ./ -type f -maxdepth 3 2>/dev/null ) ;
for $k (keys %files_ext) { say $k if $files_ext{$k} eq ".pdf" } ;'
然后您可以将其重写为脚本:
use v5.22;
use File::Basename ;
use List::Util 'any';
my %files_ext ;
my @ext = qw(.doc .xls) ;
my @list = qx( find ./ -type f -maxdepth 3 2>/dev/null ) ;
map {
chomp;
$files_ext{$_} = ( fileparse($_, qr/\..[^.]*$/))[2]
} @list ;
for my $k (keys %files_ext) {
say $k if (any { $_ eq $files_ext{$k} } @ext ) ;
}
但是,您可以使用各种模块之一来帮助您使用 perl 查找文件,而无需运行系统命令,而不是使用这种方式构建哈希来过滤文件。 例如 File::Find 随核心 perl 发行版一起提供。来自CPAN,我的最爱之一是Path:::Iterator::Rule。由于您的问题询问如何将find 的输出添加到哈希中,因此我的答案集中在该方法上。
这是一个脚本,它使用Path::Iterator::Rule 来查找文件,然后像上面一样过滤结果。
use File::Basename ;
use List::Util 'any';
use Path::Iterator::Rule;
my @exts = qw(.doc .xls);
my $rule = Path::Iterator::Rule->new()->max_depth(3);
my @dirs = $rule->all( "." ) ;
for my $file ( @dirs ) {
if ( any { $_ eq ( fileparse($file, qr/\..[^.]*$/))[2] } @exts ) {
print "$file \n" ;
}
}
在大量文件上,通过将 ->all() 方法替换为 ->all_fast() 或移动过滤部分(即对any() 和fileparse()) 的调用进入一个自定义规则,该规则使用匿名子例程sub{ ...} 直接构造过滤后的文件列表。
使用“惰性”迭代器方法->iter() 或->iter_fast()而不是列表接口似乎也有帮助:
use File::Basename;
use List::Util 'any';
use Path::Iterator::Rule;
my @exts = qw(.doc .xls);
my $rule = Path::Iterator::Rule->new()->max_depth(3);
$rule->and(
sub {
my $ext = ( fileparse($_, qr/\..[^.]*$/))[2];
any { $_ eq $ext } @exts;
}
);
my $next = $rule->iter_fast(".");
while (defined(my $file = $next->())) {
print "$file\n";
}
在我的系统上,使用对 Unix 的系统调用 find() 是最快的。不过,快速并不总是“最好的”。 perl 模块可以为您提供错误处理和安全性,否则您将无法通过简单地读取系统命令的输出来获得。
其他参考资料