NAME
File::Find::Rule - Alternative interface to File::Find
SYNOPSIS
use File::Find::Rule;# find all the subdirectories of a given directorymy @subdirs = File::Find::Rule->directory->in( $directory );# find all the .pm files in @INCmy @files = File::Find::Rule->file()->name( '*.pm' )->in( @INC );# as above, but without method chainingmy $rule = File::Find::Rule->new;$rule->file;$rule->name( '*.pm' );my @files = $rule->in( @INC );
DESCRIPTION
File::Find::Rule is a friendlier interface to File::Find. It allows you to build rules which specify the desired files and directories.
METHODS
- "new"
-
A constructor. You need not invoke
"new"manually unless you wish to, as each of the rule-making methods will auto-create a suitable object if called as class methods.
Matching Rules
- name( @patterns )
-
Specifies names that should match. May be globs or regular expressions.
$set->name( '*.mp3', '*.ogg' ); # mp3s or oggs$set->name( qr/\.(mp3|ogg)$/ ); # the same as a regex$set->name( 'foo.bar' ); # just things named foo.bar
- -X tests
-
Synonyms are provided for each of the -X tests. See "-X" in perlfunc for details. None of these methods take arguments.
Test | Method Test | Method------|------------- ------|-----------------r | readable -R | r_readable-w | writeable -W | r_writeable-w | writable -W | r_writable-x | executable -X | r_executable-o | owned -O | r_owned| |-e | exists -f | file-z | empty -d | directory-s | nonempty -l | symlink| -p | fifo-u | setuid -S | socket-g | setgid -b | block-k | sticky -c | character| -t | tty-M | modified |-A | accessed -T | ascii-C | changed -B | binaryThough some tests are fairly meaningless as binary flags (
"modified","accessed","changed"), they have been included for completeness.# find nonempty files$rule->file,->nonempty;
- stat tests
-
The following
"stat"based methods are provided:"dev","ino","mode","nlink","uid","gid","rdev","size","atime","mtime","ctime","blksize", and"blocks". See "stat" in perlfunc for details.Each of these can take a number of targets, which will follow Number::Compare semantics.
$rule->size( 7 ); # exactly 7$rule->size( ">7Ki" ); # larger than 7 * 1024 * 1024 bytes$rule->size( ">=7" )->size( "<=90" ); # between 7 and 90, inclusive$rule->size( 7, 9, 42 ); # 7, 9 or 42
- any( @rules )
- or( @rules )
-
Allows shortcircuiting boolean evaluation as an alternative to the default and-like nature of combined rules.
"any"and"or"are interchangeable.# find avis, movs, things over 200M and empty files$rule->any( File::Find::Rule->name( '*.avi', '*.mov' ),File::Find::Rule->size( '>200M' ),File::Find::Rule->file->empty,);
- none( @rules )
- not( @rules )
-
Negates a rule. (The inverse of
"any".)"none"and"not"are interchangeable.# files that aren't 8.3 safe$rule->file->not( $rule->new->name( qr/^[^.]{1,8}(\.[^.]{0,3})?$/ ) );
- "prune"
-
Traverse no further. This rule always matches.
- "discard"
-
Don't keep this file. This rule always matches.
- "exec( \&subroutine( $shortname, $path, $fullname ) )"
-
Allows user-defined rules. Your subroutine will be invoked with
$_set to the current short name, and with parameters of the name, the path you're in, and the full relative filename.Return a true value if your rule matched.
# get things with long names$rules->exec( sub { length > 20 } );
- grep( @specifiers )
-
Opens a file and tests it each line at a time.
For each line it evaluates each of the specifiers, stopping at the first successful match. A specifier may be a regular expression or a subroutine. The subroutine will be invoked with the same parameters as an ->exec subroutine.
It is possible to provide a set of negative specifiers by enclosing them in anonymous arrays. Should a negative specifier match the iteration is aborted and the clause is failed. For example:
$rule->grep( qr/^#!.*\bperl/, [ sub { 1 } ] );Is a passing clause if the first line of a file looks like a perl shebang line.
- maxdepth( $level )
-
Descend at most
$level(a non-negative integer) levels of directories below the starting point.May be invoked many times per rule, but only the most recent value is used.
- mindepth( $level )
-
Do not apply any tests at levels less than
$level(a non-negative integer).
- extras( \%extras )
-
Specifies extra values to pass through to
"File::File::find"as part of the options hash.For example this allows you to specify following of symlinks like so:
my $rule = File::Find::Rule->extras({ follow => 1 });May be invoked many times per rule, but only the most recent value is used.
- "relative"
-
Trim the leading portion of any path found
- "canonpath"
-
Normalize paths found using
"File::Spec-"canonpath>. This will return paths with a file-seperator that is native to your OS (as determined by File::Spec),
instead of the default"/".For example, this will return
"tmp/foobar"on Unix-ish OSes and"tmp\foobar"on Win32.
- "not_*"
-
Negated version of the rule. An effective shortand related to ! in the procedural interface.
$foo->not_name('*.pl');$foo->not( $foo->new->name('*.pl' ) );
Query Methods
- in( @directories )
-
Evaluates the rule, returns a list of paths to matching files and directories.
- start( @directories )
-
Starts a find across the specified directories. Matching items may then be queried using "match". This allows you to use a rule as an iterator.
my $rule = File::Find::Rule->file->name("*.jpeg")->start( "/web" );while ( defined ( my $image = $rule->match ) ) {...}
- "match"
-
Returns the next file which matches, false if there are no more.
Extensions
Extension modules are available from CPAN in the File::Find::Rule namespace. In order to use these extensions either use them directly:
use File::Find::Rule::ImageSize;use File::Find::Rule::MMagic;# now your rules can use the clauses supplied by the ImageSize and# MMagic extension
or, specify that File::Find::Rule should load them for you:
use File::Find::Rule qw( :ImageSize :MMagic );
For notes on implementing your own extensions, consult File::Find::Rule::Extending
Further examples
- Finding perl scripts
-
my $finder = File::Find::Rule->or(File::Find::Rule->name( '*.pl' ),File::Find::Rule->exec(sub {if (open my $fh, $_) {my $shebang = <$fh>;close $fh;return $shebang =~ /^#!.*\bperl/;}return 0;} ),);Based upon this message http://use.perl.org/comments.pl?sid=7052&cid=10842
- ignore CVS directories
-
my $rule = File::Find::Rule->new;$rule->or($rule->new->directory->name('CVS')->prune->discard,$rule->new);Note here the use of a null rule. Null rules match anything they see, so the effect is to match (and discard) directories called 'CVS' or to match anything.
TWO FOR THE PRICE OF ONE
File::Find::Rule also gives you a procedural interface. This is documented in File::Find::Rule::Procedural
EXPORTS
"find", "rule"
TAINT MODE INTERACTION
As of 0.32 File::Find::Rule doesn't capture the current working directory in a taint-unsafe manner. File::Find itself still does operations that the taint system will flag as insecure but you can use the "extras" feature to ask File::Find to internally "untaint" file paths with a regex like so:
my $rule = File::Find::Rule->extras({ untaint => 1 });
Please consult File::Find's documentation for "untaint", "untaint_pattern", and "untaint_skip" for more information.
BUGS
The code makes use of the "our" keyword and as such requires perl version 5.6.0 or newer.
Currently it isn't possible to remove a clause from a rule object. If this becomes a significant issue it will be addressed.
AUTHOR
Richard Clamp <[email protected]> with input gained from this use.perl discussion: http://use.perl.org/~richardc/journal/6467
Additional proofreading and input provided by Kake, Greg McCarroll, and Andy Lester [email protected].
COPYRIGHT
Copyright (C) 2002, 2003, 2004, 2006, 2009, 2011 Richard Clamp. All Rights Reserved.
This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
SEE ALSO
File::Find, Text::Glob, Number::Compare, find(1)
If you want to know about the procedural interface, see File::Find::Rule::Procedural, and if you have an idea for a neat extension File::Find::Rule::Extending