Reputation: 197
I want to find file that does not contain the specific string? The listed file is like below
../../../experiment/fileA.txt (contain word 'Book')
../../../experiment/fileB.txt (contain word 'Book')
../../../experiment/fileC.txt (do not contain word 'Book')
../../../experiment/fileD.txt (contain word 'Book')
Here is my code
use strict;
use warning;
my $dirname = "../../../experiment/";
my $keyword = "Book";
my @result;
my $find_file = sub {
my $F = $File::Find::name;
if ($F =~ /txt$/) {
open my $in, "<", $F or die $!;
while(<$in>) {
if (/\Q$keyword\E/){
next;
}else{
push @result, $F;
return;
}
}
}
};
find ({ wanted => $find_file, no_chdir=>1}, $dirname );
foreach my $result (@result){
chomp $result;
$result =~ s{.*/}{};
print "$result\n";
}
But it seem does not work. It display all file whether it has the $keyword or not. I only want it to display only if the file does not have the $keyword
Upvotes: 1
Views: 168
Reputation: 9231
Path::Iterator::Rule makes tasks like this really simple. As a side note, I would recommend resolving the directory to an absolute path before iterating.
use strict;
use warnings;
use Cwd 'abs_path';
use File::Basename;
use Path::Iterator::Rule;
my $dirname = abs_path "../../../experiment/";
my $keyword = "Book";
my $rule = Path::Iterator::Rule->new->not_dir->name(qr/txt$/)->not_line_match(qr/\Q$keyword\E/);
my $next = $rule->iter($dirname);
while (defined(my $file = $next->())) {
print basename($file), "\n";
}
Upvotes: 1
Reputation: 66881
There's a simple logic error. The code goes through lines of each file
while (<$in>) {
if (/\Q$keyword\E/){
next;
} else {
push @result, $F;
return;
}
}
and as soon as any one line doesn't have $keyword
it adds the file to @result
.
You need to check all lines and if $keyword
is never found only then add a file. The easiest way to do this is to return
from the sub as soon as the thing is found
while (<$in>) {
return if /\Q$keyword/;
}
push @result, $F;
Upvotes: 4
Reputation: 93676
This doesn't address your code, but I'd like to point out that with the grep
command on any Linux system you can do exactly what it looks like you're trying to do with this command:
grep -L Book -R ../../../experiment/
Upvotes: 2