Learning Perl on Win32 Systems

Learning Perl on Win32 SystemsSearch this book
Previous: 12.1 Moving Around the Directory TreeChapter 12
Directory Access
Next: 12.3 Directory Handles
 

12.2 Globbing

The command prompt usually takes a solitary asterisk (*) command-line argument and turns it into a list of all of the filenames in the current directory. So, when you say del *, you'll remove all of the files from the current directory. (Don't try this unless you like restoring the current directory from your backup device.) Similarly, *.c as a command-line argument turns into a list of all filenames in the current directory that end in .c, and c:\temp\backup* is a list of all filenames in the directory c:\temp that begin with backup. (If this information is new to you, you probably want to read some more about using the command line somewhere else before proceeding.)

The expansion of arguments like * or *.c into the list of matching filenames is called globbing. Perl supports globbing through a very simple mechanism - just put the globbing pattern between angle brackets or use the more mnemonically named glob function, like this:

@a = <*.plx>;
@a = glob("*.plx");

In a list context, as demonstrated here, the glob returns a list of all names that match the pattern or an empty list if none match. In a scalar context, the next name that matches is returned, or undef is returned if there are no more matches; this process is very similar to reading from a filehandle. For example, to look at one name at a time:

while (defined($nextname = <c:/scripts/*.plx>)) {
        print "one of the files is $nextname\n";
}

Here the returned filenames begin with c:\scripts\, so that if you want just the last part of the name, you'll have to whittle it down yourself, like so:

while ($nextname = <c:/scripts/*.plx>) {
    $nextname =~ s#.*/##; # remove part before last slash
    print "one of the files is $nextname\n";
}

Multiple patterns are permitted inside the file glob argument; the lists are constructed separately and then concatenated as if they were one big list:

@fred_barney_files = <fred* barney*>;

In other words, the glob returns the same values that an equivalent dir /B command with the same parameters would return.

Although file globbing and regular-expression matching function similarly, the meanings of their various special characters are quite different. Don't confuse the two, or you'll be wondering why <\.c$> doesn't find all of the files that end in .c!

The argument to glob is variable interpolated before expansion. You can use Perl variables to select a wildcard based on a string computed at runtime:

if (-d "c:/tmp") {
        $where = "c:/tmp";
} else {
        $where = "c:/temp";
}
@files = <$where/*>;

Here we set $where to be one of two different directory names, based on whether or not the directory c:\tmp exists.[3] We then get a list of files in the selected directory. Note that the $where variable is expanded, which means the wildcard to be globbed is either c:\tmp\* or c:\temp\*.

[3] If we were really trying to find where the temporary directory was, we'd be checking the ENV hash for the TEMP variable:

my $tmp = $ENV{'TEMP'} || $ENV{'TMP'};

There's one exception to this rule: the pattern <$var> (meaning to use the variable $var as the entire glob expression) must be written as <${var}> for reasons we'd rather not get into at this point.[4]

[4] The construct <$fred> reads a line from the filehandle named by the contents of the scalar variable $fred. Together with some other features not covered in this book, this construct enables you to use indirect filehandles in which the name of a handle is passed around and manipulated as if it were data.


Previous: 12.1 Moving Around the Directory TreeLearning Perl on Win32 SystemsNext: 12.3 Directory Handles
12.1 Moving Around the Directory TreeBook Index12.3 Directory Handles