File::Finder::Steps(3pm) | User Contributed Perl Documentation | File::Finder::Steps(3pm) |
File::Finder::Steps - steps for File::Finder
## See File::Finder for normal use of steps ## subclassing example: BEGIN { package My::File::Finder; use base File::Finder; sub _steps_class { "My::File::Finder::Steps" } } BEGIN { package My::File::Finder::Steps; use base File::Finder::Steps; sub bigger_than { # true if bigger than N bytes my $self = shift; my $bytes = shift; return sub { -s > $bytes; } } } my $over_1k = My::File::Finder->bigger_than(1024); print "Temp files over 1k:\n"; $over_1k->ls->in("/tmp");
"File::Finder::Steps" provide the predicates being tested for "File::Finder".
These methods are called on a class or instance to add a "step". Each step adds itself to a list of steps, returning the new object. This allows you to chain steps together to form a formula.
As in find, the default operator is "and", and short-circuiting is performed.
my $big_or_old = File::Finder ->type('f') ->left ->size("+100")->or->mtime("+90") ->right; find($big_or_old->ls, "/tmp");
You need parens because the "or" operator is lower precedence than the implied "and", for the same reason you need them here:
find /tmp -type f '(' -size +100 -o -mtime +90 ')' -print
Without the parens, the -type would bind to -size, and not to the choice of -size or -mtime.
Mismatched parens will not be found until the formula is used, causing a fatal error.
# list all non-files in /tmp File::Finder->not->type('f')->ls->in("/tmp");
... ->left-> ...[might return false]... ->or->true->right-> ...
Of course, this is the find command's idiom of:
find .... '(' .... -o -true ')' ...
# list all files and dirs, but don't descend into CVS dir contents: File::Finder->type('d')->name('CVS')->prune->comma->ls->in('.');
my $pm_files = File::Finder->name('*.pm')->in('.'); my $pm_files_too = File::Finder->name(qr/pm$/)->in('.');
my $files = File::Finder->type('f'); # find files that are exactly mode 644 my $files_644 = $files->perm(0644); # find files that are at least world executable: my $files_world_exec = $files->perm("-1"); # find files that have some executable bit set: my $files_exec = $files->perm("+0111");
Note that I couldn't figure out how to horse around with the current directory very well, so I'm using $_ here instead of the more traditional "File::Find::name". It still works, because we're still chdir'ed down into the directory, but it looks weird on a trace. Trigger "no_chdir" in "find" if you want a traditional find full path.
my $f = File::Finder->exec('ls', '-ldg', '{}'); find({ no_chdir => 1, wanted => $f }, @starting_dirs);
Yeah, it'd be trivial for me to add a no_chdir method. Soon.
my $blaster = File::Finder->atime("+30")->eval(sub { unlink });
But wait, there's more. If the parameter is an object that responds to "as_wanted", that method is automatically called, hoping for a coderef return. This neat feature allows subroutines to be created and nested:
my $old = File::Finder->atime("+30"); my $big = File::Finder->size("+100"); my $old_or_big = File::Finder->eval($old)->or->eval($big); my $killer = File::Finder->eval(sub { unlink }); my $kill_old_or_big = File::Finder->eval($old_or_big)->ls->eval($killer); $kill_old_or_big->in('/tmp');
Almost too cool for words.
require File::Finder; require File::Find::Rule; require File::Find::Rule::ImageSize; my $ffr = File::Find::Rule->file->image_x('>1000')->image_y('>1000'); my @big_friends = File::Finder->ffr($ffr) ->in("/Users/merlyn/Pictures/Sorted/Friends");
my $plugh_files = File::Finder->type('f')->contains(qr/plugh/);
Searching is performed on a line-by-line basis, respecting the current value of $/.
A step consists of a compile-time and a run-time component.
During the creation of a "File::Finder" object, step methods are called as if they were methods against the slowly-growing "File::Finder" instance, including any additional parameters as in a normal method call. The step is expected to return a coderef (possibly a closure) to be executed at run-time.
When a "File::Finder" object is being evaluated as the "File::Find" "wanted" routine, the collected coderefs are evaluated in sequence, again as method calls against the "File::Finder" object. No additional parameters are passed. However, the normal "wanted" values are available, such as $_, $File::Find::name, and so on. The "_" pseudo-handle has been set properly, so you can safely use "-X" filetests and "stat" against the pseudo-handle. The routine is expected to return a true/false value, which becomes the value of the step.
Although a "File::Finder" object is passed both to the compile-time invocation and the resulting run-time invocation, only the "options" self-hash element is properly duplicated through the cloning process. Do not be tempted to add additional self-hash elements without overriding "File::Finder"'s "_clone". Instead, pass values from the compile-time phase to the run-time phase using closure variables, as shown in the synopsis.
For simplicity, you can also just mix-in your methods to the existing "File::Finder::Steps" class, rather than subclassing both classes as shown above. However, this may result in conflicting implementations of a given step name, so beware.
File::Finder
None known yet.
Randal L. Schwartz, <merlyn@stonehenge.com>
Copyright (C) 2003,2004 by Randal L. Schwartz, Stonehenge Consulting Services, Inc.
This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself, either Perl version 5.8.2 or, at your option, any later version of Perl 5 you may have available.
2022-11-19 | perl v5.36.0 |