Reputation: 21
I am using
File::Find::Rule
in the following piece of code to search recursively for
a file within a given directory.
my $WD = Cwd::abs_path();
my @files = File::Find::Rule->file()->relative()->name( '*.txt' )->in($WD);
for my $file ( @files ) {
print "file: $file\n";
}
|--- DIR1
|-- subdir1
|-- *.txt
|-- subdir2
|-- *.txt
|-- *.txt
DIR1/subdir1/*.txt
DIR1/subdir2/*.txt
DIR1/subdir2/*.txt
DIR1/subdir1/*.txt
Can someone please suggest what can be done?
Upvotes: 2
Views: 177
Reputation: 66899
One way is to use its exec
, in order to stop matching once the path of files found changes
my @files = File::Find::Rule->file->relative->name('*.txt')
->exec( sub {
state $path = '';
return 0 if $path and $path ne $_[1];
$path = $_[1];
}
)->in($WD);
The subroutine in exec
is invoked once the files are found, and in it the path to files is available as the second argument in @_
. Once that path changes from what it had been up to that point it means that the search has found files in a different directory.
As soon as that happens we stop changing $path
so all further queries on that directory fail.
This is a simple way to detect change of directories in which files are found. Check by replacing return 0
with, for example, say "Changed from $path to $_[1]";
.
Tested as perl -Mstrict -MFile::Find::Rule -wE'...'
, and '
in code were "
.
Note: you need use feature 'state';
for state (unless you are under use v5.10
or higher). In a one-liner the -E
(as opposed to -e
) enables all features, in the main compilation unit.
Early comments changed (or obscured) the requirement in the title to abort altogether under the stated condition. In that case die
instead of return 0
, inside eval
my @files;
eval {
@files = File::Find::Rule->file->relative->name('*>txt')
->exec( sub {
state $path = '';
die "CHANGED_DIR\n" if $path and $path ne $_[1];
$path = $_[1];
})
->in($WD);
} or do { die $@ if $@ ne 'CHANGED_DIR' }
where the string for die
is made up only so that we can check and re-throw if needed.
Upvotes: 2