File::Find(3perl) | Perl Programmers Reference Guide | File::Find(3perl) |
File::Find - Traverse a directory tree.
use File::Find; find(\&wanted, @directories_to_search); sub wanted { ... } use File::Find; finddepth(\&wanted, @directories_to_search); sub wanted { ... } use File::Find; find({ wanted => \&process, follow => 1 }, '.');
These are functions for searching through directory trees doing work on each file found similar to the Unix find command. File::Find exports two functions, "find" and "finddepth". They work similarly but have subtle differences.
find(\&wanted, @directories); find(\%options, @directories);
"find()" does a depth-first search over the given @directories in the order they are given. For each file or directory found, it calls the &wanted subroutine. (See below for details on how to use the &wanted function). Additionally, for each directory found, it will "chdir()" into that directory and continue the search, invoking the &wanted function on each file or subdirectory in the directory.
finddepth(\&wanted, @directories); finddepth(\%options, @directories);
"finddepth()" works just like "find()" except that it invokes the &wanted function for a directory after invoking it for the directory's contents. It does a postorder traversal instead of a preorder traversal, working from the bottom of the directory tree up where "find()" works from the top of the tree down.
The first argument to "find()" is either a code reference to your &wanted function, or a hash reference describing the operations to be performed for each file. The code reference is described in "The wanted function" below.
Here are the possible keys for the hash:
This is a no-op on Win32.
This is also a no-op on Win32.
"follow_skip==0" causes File::Find to die if any file is about to be processed a second time.
"follow_skip==2" causes File::Find to ignore any duplicate files and directories but to proceed normally otherwise.
The "wanted()" function does whatever verifications you want on each file and directory. Note that despite its name, the "wanted()" function is a generic callback function, and does not tell File::Find if a file is "wanted" or not. In fact, its return value is ignored.
The wanted function takes no arguments but rather does its work through a collection of variables.
The above variables have all been localized and may be changed without affecting data outside of the wanted function.
For example, when examining the file /some/path/foo.ext you will have:
$File::Find::dir = /some/path/ $_ = foo.ext $File::Find::name = /some/path/foo.ext
You are chdir()'d to $File::Find::dir when the function is called, unless "no_chdir" was specified. Note that when changing to directories is in effect, the root directory (/) is a somewhat special case inasmuch as the concatenation of $File::Find::dir, '/' and $_ is not literally equal to $File::Find::name. The table below summarizes all variants:
$File::Find::name $File::Find::dir $_ default / / . no_chdir=>0 /etc / etc /etc/x /etc x no_chdir=>1 / / / /etc / /etc /etc/x /etc /etc/x
When "follow" or "follow_fast" are in effect, there is also a $File::Find::fullname. The function may set $File::Find::prune to prune the tree unless "bydepth" was specified. Unless "follow" or "follow_fast" is specified, for compatibility reasons (find.pl, find2perl) there are in addition the following globals available: $File::Find::topdir, $File::Find::topdev, $File::Find::topino, $File::Find::topmode and $File::Find::topnlink.
This library is useful for the "find2perl" tool (distributed as part of the App-find2perl CPAN distribution), which when fed,
find2perl / -name .nfs\* -mtime +7 \ -exec rm -f {} \; -o -fstype nfs -prune
produces something like:
sub wanted { /^\.nfs.*\z/s && (($dev, $ino, $mode, $nlink, $uid, $gid) = lstat($_)) && int(-M _) > 7 && unlink($_) || ($nlink || (($dev, $ino, $mode, $nlink, $uid, $gid) = lstat($_))) && $dev < 0 && ($File::Find::prune = 1); }
Notice the "_" in the above "int(-M _)": the "_" is a magical filehandle that caches the information from the preceding "stat()", "lstat()", or filetest.
Here's another interesting wanted function. It will find all symbolic links that don't resolve:
sub wanted { -l && !-e && print "bogus link: $File::Find::name\n"; }
Note that you may mix directories and (non-directory) files in the list of directories to be searched by the "wanted()" function.
find(\&wanted, "./foo", "./bar", "./baz/epsilon");
In the example above, no file in ./baz/ other than ./baz/epsilon will be evaluated by "wanted()".
See also the script "pfind" on CPAN for a nice application of this module.
If you run your program with the "-w" switch, or if you use the "warnings" pragma, File::Find will report warnings for several weird situations. You can disable these warnings by putting the statement
no warnings 'File::Find';
in the appropriate scope. See warnings for more info about lexical warnings.
If you do set $File::Find::dont_use_nlink to 0, you may notice an improvement in speed at the risk of not recursing into subdirectories if a filesystem doesn't populate "nlink" as expected.
$File::Find::dont_use_nlink now defaults to 1 on all platforms.
Despite the name of the "finddepth()" function, both "find()" and "finddepth()" perform a depth-first search of the directory hierarchy.
File::Find used to produce incorrect results if called recursively. During the development of perl 5.8 this bug was fixed. The first fixed version of File::Find was 1.01.
find(1), find2perl.
2023-11-25 | perl v5.32.1 |