Perl Advent Calendar 2006-12-02

Peeking under the tree

by Shlomi Fish & Jerrad Pierce

The first author is one of the current maintainers of today's package from Olivier Thauvin.

Most perl hackers are familiar with the module, File::Find, which has been shipped with the core distribution since 5.000 and works well. File::Find (FF) is used to recursively scan a directory tree and execute user code. Several modules offering a softer, higher-level interfaces to it have cropped up on CPAN such as File::Find::Rule and File::Finder.

File::Find is very robust, but not without its drawbacks. Among its most serious limitations are:

Introducing File::Find::Object

File::Find::Object (FFO) provides an OO alternative to File::Find which addresses both of these deficiencies. Like FF, the constructor accepts a list of directories to scan which are then traversed one by one. And while FFO provides a backwards compatible callback based interface, the recommended mode of use is to retrieve results via the next() method. Several other esoteric traversal-control functions are also provided:

Our example below is a simple command line application that searches for the first file or directory with a filename matching the supplied certain pattern and reports some information about it.

   1 #!/usr/bin/perl
   3 use strict;
   4 use warnings;
   6 use File::Find::Object;
   7 use File::Basename;
   9 my $pattern_str = shift;
  10 my @dirs = @ARGV;
  12 my $pattern = qr/$pattern_str/;
  14 my $ff = File::Find::Object->new({}, @dirs);
  16 my $result;
  18 while (defined($result = $ff->next()))
  19 {
  20     if (basename($result) =~ m{$pattern})
  21     {
  22         last RESULTS_LOOP;
  23     }
  24 }
  26 # Now we've exited from the loop and can do something with $result.
  28 my @stat = stat($result);
  29 print sprintf("Found the file \"%s\" of size %i, modified at %s\n",
  30     $result,
  31     $stat[7],
  32     scalar(localtime($stat[9]))
  33 );

See Also

There are several similar modules to FFO including File::Find::Iterator, File::Walker and the unmaintained File::FTS. Also of possible interest is Randal L. Schwartz's column that implements directory traversal using a tied hash.