How to use File::Find to recursively search directories in Perl?
Question
How to use File::Find to recursively search directories in Perl?
File::Find is a core Perl module designed for recursively traversing directory trees. It allows you to process every file and directory under a given root path by calling a user-defined subroutine for each entry found. This makes it especially useful for tasks like searching for specific files, gathering information, or performing bulk operations on file systems.
How File::Find Works
The key function in File::Find is find(). You provide it a callback and a starting directory (or directories). It recursively descends into all subdirectories and invokes your callback for each file or directory found. Your callback can then inspect or act on the current item.
The module automates the directory traversal logic, and you get the current entry's name in the global variable $File::Find::name, which is the full path, and the name relative to the current directory in $_. This is typical Perl context handling: $_ is localized in the callback to the basename of the current file/directory.
Basic Syntax
find(\&wanted, $directory): Calls&wantedon each file/dir recursively under$directory.- Inside
&wanted,$_is the current filename (not full path). $File::Find::nameis the full path of the current item.
Example: Recursively Find All .pl Files
use strict;
use warnings;
use File::Find;
# Callback run for each file/dir found
sub wanted {
# We want only files ending with .pl
if (-f $_ and $_ =~ /\.pl$/) {
print "Found Perl script: $File::Find::name\n";
}
}
my $start_dir = '.';
# Start the recursive search at $start_dir
find(\&wanted, $start_dir);
This script recursively searches from the current directory, printing the full path of every file ending in .pl.
Explanation of Perl Concepts
- Sigils:
$for scalars ($_,$File::Find::name) and&for subroutine references (&wantedor\&wanted). - Context: File::Find localizes
$_for each file name in the callback, so you naturally work on it as the current entry's basename. - TMTOWTDI: Perl offers various ways to express recursion or file searching;
File::Findis classic and efficient for this.
Common Pitfalls
$_only contains the basename, so do not assume it is the full path.- The full path is always in
$File::Find::name. Use this when opening files or printing paths. - File::Find changes your working directory (
chdir) under the hood to optimize calls - if you call other functions within your callback that rely on cwd, be cautious. - The order of traversal is undefined; do not rely on a specific order.
- The
findfunction expects at least one directory argument or arrayref. Passing nothing will cause errors.
Additional Tips
- You can pass multiple start directories as an array reference to
find(). - Starting with Perl 5.10+, you can use the
File::Find::finddepth()function for post-order traversal (visit children before parents). - To skip a directory subtree, use
$File::Find::prune = 1;inside yourwantedsubroutine.
Using File::Find is an elegant, efficient way to recursively scan directories in Perl without manually managing recursion or directory handles.
Verified Code
Executed in a sandbox to capture real output. • v5.34.1 • 571ms
(empty)Can't cd to (./) EXPR: Permission denied
at - line 16.