Previous Page
Next Page

8.11. Globbing

Use glob, not <...>.

The <...> syntax is heavily associated with I/O in most people's minds. So something like this:

    my @files = <*.pl>;

is easy to mistake for a normal readline operation:

    my @files = <$fh>;

Unfortunately, the first version isn't an input operation at all. Angle brackets are input operators only when they're empty (<>), or when they contain a bareword identifier (<DATA>), or when they contain a simple scalar variable (<$input_file>). If anything else appears inside the angles, they perform shell-based directory look-up instead.

In other words, the <*.pl> operation takes the contents of the angle brackets (i.e., *.pl), passes them to the csh system shell[*], collects the list of filenames that match this shell pattern, and returns those names.

[*] Under more recent versions of Perl, the shell pattern is expanded by the interpreter itself. See the standard File::Glob module for details.

It's not bad enough that this "file glob" is easy to confuse with a popular I/O operation. Far worse, if you apply other best practices when writing itsuch as factoring the fixed shell pattern out into a named constantit suddenly transforms into the very I/O operation it previously only looked like:

    Readonly my $FILE_PATTERN => '*.pl';

    # and later...

    my @files = <$FILE_PATTERN>;    # KABOOM! (probably)

As mentioned earlier, a scalar variable in angles is one of the three valid forms that invoke a readline call in Perl, which means that the refactored operation isn't a file glob specification any more. Instead, the angles attempt to do a readline, discover that $FILE_PATTERN contains the string '*.pl', and head straight off to the symbol table looking for a filehandle of that name. Unless the coder has been truly evil, there won't be such a filehandle[] and, instead of the expected file list appearing in @files, a 'readline( ) on unopened filehandle' exception will be thrown.

[] They would have to have written something like:

    no strict 'refs'; open *{'*.pl'}, '<', $filename;

in which case the calamity that is about to befall them is a clear case of Instant Justice.

A construct that breaks when you attempt to improve its readability is, by definition, unmaintainable. The file globbing operation has a proper name:

    my @files = glob($FILE_PATTERN);

Use it, and keep the angle brackets strictly for input operations.

    Previous Page
    Next Page