use warnings;
use strict;
use feature 'say';
use Data::Dump; # dd
use Path::Tiny; # path
my $dir = shift // '.';
my $pattern = qr/word/;
my $ret = path($dir)->visit(
sub {
my ($entry, $state) = @_;
return if not -f;
for ($entry->lines) {
if (/$pattern/) {
print "$entry: $_";
push @{$state->{$entry}}, $_;
}
}
},
{ recurse => 1 }
);
dd $ret; # print the returned complex data structure
my $iter = path($dir)->iterator({ recurse => 1 });
my $info;
while (my $e = $iter->()) {
next if not -f $e;
# process the file $e as needed
#/$pattern/ and push @{$info->{$e}}, $_ and print "$e: $_"
# for $e->lines
}
use warnings;
use strict;
use feature 'say';
use File::Find;
my @dirs = @ARGV ? @ARGV : '.';
my $pattern = qr/word/;
my %res;
find( sub {
return if not -T; # ASCII or UTF-8 only
open my $fh, '<', $_ or do {
warn "Error opening $File::Find::name: $!";
return;
};
while (<$fh>) {
if (/$pattern/) {
chomp;
push @{$res{$File::Find::name}}, $_
}
}
}, @dirs
);
for my $k (keys %res) {
say "In file $k:";
say "\t$_" for @{$res{$k}};
}
1条答案
按热度按时间dphi5xsq1#
这是一个相当规范的任务,而我无法找到直接的答案与一个可能是最简单的和最简单的工具的工作,方便的Path::Tiny
这里使用
lines
读取文件的方式只是其中一种方式。它可能不适合非常大的文件,因为它一次读取所有行,在这种情况下最好逐行读取。visit
方法基于iterator
,它也可以干净地完成此任务在这里,我们必须提供一个数据结构来积累信息,但我们得到了更多的灵活性。
上面使用的“普通”文件的-f filetest仍然有些宽松;它允许交换文件,例如,一些编辑器在会话期间保留的文件(例如vim)。这些文件将导致所有类型的匹配。要使用纯ASCII或UTF-8文件,请使用
-T
test。另外,还有用于递归遍历和搜索的库,例如File::Find(或File::Find::Rule)或Path::Iterator::Rule。
为了完整起见,这里是内核File::Find的一个例子