File::Find::Rule(3)

🌸 NAME 🌸

okay so bestie, this is the File::Find::Rule(3) man page, and it's literally the alternative interface to File::Find β€” like File::Find but with main character energy, no cap πŸ’…


✨ SYNOPSIS ✨

use File::Find::Rule;
# find all the subdirectories of a given directory
my @subdirs = File::Find::Rule->directory->in( $directory );

# find all the .pm files in @INC
my @files = File::Find::Rule->file()
                            ->name( '*.pm' )
                            ->in( @INC );

# as above, but without method chaining
my $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 lets you build rules which specify the desired files and directories. it's giving "glow-up for a classic module" and honestly? obsessed 🫢


πŸ’… 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. so like, it's very "I got you, bestie" energy ✨

πŸŽ€ 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  |  binary

Though some tests are fairly meaningless as binary flags (modified, accessed, changed), they have been included for completeness. iykyk 🧚

# 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. so you can be like "give me exactly this, or a range, or a few options" β€” very flexible, slay πŸ’–

$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. very "choose your fighter" of them ✨
# 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. the way that negation just works 😭
# 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. it's like "okay we're done here, bye" πŸ‘‹
  • discard β€” Don't keep this file. This rule always matches. literally "not you, next" πŸ’€
  • 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. custom rules? we love to see it πŸŽ€

# 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. okay so very "line by line, no skips" energy πŸ”

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. periodt 🐍

  • 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. so like, last one wins, bestie πŸ’…

  • mindepth( $level ) β€” Do not apply any tests at levels less than $level (a non-negative integer). it's giving "don't even look at me until you're deep enough" πŸ™ˆ
  • 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. again: latest wins, no cap 🌈

  • relative β€” Trim the leading portion of any path found. short king behavior βœ‚οΈ
  • 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. it's giving "native separator realness" πŸ¦‹

  • not_* β€” Negated version of the rule. An effective shortand related to ! in the procedural interface. yes, shortand β€” that's what the page says, and we respect the page 😌
$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. the classic "give me the list" move ✨
  • 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. so main character energy: one match at a time πŸ’…
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. literally "next!" until there's no next 😭

🧚 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. build your own little plugin era, we love that for you πŸŽ€

🌈 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 β€” shoutout to the source, we love a citation πŸ’–

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. null rule = the chillest rule, fr fr 🌸


πŸ‘‘ TWO FOR THE PRICE OF ONE πŸ‘‘

File::Find::Rule also gives you a procedural interface. This is documented in File::Find::Rule::Procedural. two interfaces, one module? we love a versatile icon πŸ‘‘


πŸ“ 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. taint mode said "bestie be careful" and honestly valid πŸ™ˆ


πŸ™ˆ BUGS πŸ™ˆ

The code makes use of the our keyword and as such requires perl version 5.6.0 or newer. old perl? not invited to the group chat πŸ’€

Currently it isn't possible to remove a clause from a rule object. If this becomes a significant issue it will be addressed. okay so known limitation, noted, we move 🌸


πŸ’œ AUTHOR πŸ’œ

Richard Clamp <richardc@unixbeard.net> 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 andy@petdance.com. collab era ✨


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. slay and legally clear πŸ’…


⭐ 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. go read, go build, go be iconic πŸ¦‹


and that's the whole page, bestie πŸ’– this one comes from perl v5.42.0, dated 2025-06-11, and it's literally the File::Find::Rule(3) man page. periodt πŸŽ€

πŸ“¦ where this page comes from