http://qs1969.pair.com?node_id=32791

Item Description: Enumerate files and directories in a directory tree

Review Synopsis: Use this module instead of globbing or readdir()

File::Find is the way if you want to look at all files in one or more directories. File::Find exports one function, find(), which takes two parameters, a hash or a code reference, and a list of directories where the search starts.

Why use File::Find

File::Find protects you from a lot of nasty things that happen on filesystems. In its standard configuration it ensures that your code reference is called once for each file encountered, even if there are more symlinks pointing to it, and it also prevents nasty loops for symlinked directories.

Why avoid File::Find

There is not much reason to avoid File::Find - you could want to avoid it if you want to read files in a single directory, without recursing, when you are explicitly sure that there can be no symlinks in that directory (for example, if the filesystem dosen't allow symlinks). Then, your code could load faster. But I'd file that under premature optimization.

Caveats

If you are starting to first use File::Find, you have to deal with some idiosyncrasies.

First of all, File::Find uses some "optimization" by default to speed up searches under certain filesystems under Unix. Unfortunately, this "optimization" fails to work under other filesystems, such as the iso9600 filesystem used for cdroms. ncw tells you below what to do about it - in fact, you should always use the code ncw proposes.

In the default configuration, the directory is changed to the recursed directory, and all returned filenames are relative to the current directory. Use $File::Find::name to get a fully specified filename.

If you don't want to recurse below a certain directory, there is the (not-so-well-documented) $File::Find::prune variable, which you can set to 1 in your code reference to stop recursing into the current directory.

Examples

By popular demand, here are some examples on how to use the module. The documentation shows off some interesting code, but it's not helpful if you're looking for something to get started.

A first example, printing the filename and the filename with the path to the file. The code was stolen from a node by nate.

use strict; use File::Find; sub eachFile { my $filename = $_; my $fullpath = $File::Find::name; #remember that File::Find changes your CWD, #so you can call open with just $_ if (-e $filename) { print "$filename exists!" . " The full name is $fullpath\n"; } } find (\&eachFile, "mydir/");