Directories and paths
| List a directory | |
| glob | |
| Parse and build paths | |
| Create and remove trees |
List a directory
opendir and readdir walk a directory the way open and readline walk a file. The entries arrive in filesystem order, so sort them before you show them to a person.
opendir my $dh, "/var/log" or die "opendir: $!\n";
my @entries = sort readdir $dh;
closedir $dh;
print join " ", grep { !/^\.\.?$/ } @entries;
print "\n";
perl demo.pl
apk.log
Every directory contains the entries dot and dot-dot, and almost every script filters them out. The grep above drops exactly those two names and nothing else. The /var/log of this container holds a single file, apk.log; your own system prints its own list here.
glob
glob expands a shell pattern in one call, which is shorter than opendir plus a filter when the pattern is the point. It understands stars, question marks and character classes.
my @logs = glob("/var/log/*.log");
my @confs = <*.conf>;
print "$_\n" for @logs;
perl demo.pl
/var/log/apk.log
The angle-bracket form and the function do the same thing. Prefer glob() in new code: it is a normal function call and never confused with the readline operator. The second line collects the .conf files of the current directory into @confs and prints nothing, because the directory you run from has none.
Parse and build paths
Do not split paths on slashes yourself. File::Basename knows about trailing separators, and File::Spec joins parts with the separator of the current system, which keeps scripts working on Windows.
use File::Basename qw(basename dirname);
use File::Spec;
my $full = "/var/log/app/app.log";
print basename($full), "\n"; # app.log
print dirname($full), "\n"; # /var/log/app
print File::Spec->catfile("/tmp", "out", "r.txt"), "\n";
perl demo.pl
app.log
/var/log/app
/tmp/out/r.txt
Both modules ship with Perl, so the import costs nothing. The same family provides fileparse for splitting a name into path, base and suffix.
Create and remove trees
File::Path creates a whole missing chain with make_path and removes one with remove_tree. Both return what they created or removed, and both die on a real failure such as an unwritable parent, unless you pass error => \my $err to collect the problems instead.
use File::Path qw(make_path remove_tree);
make_path("/tmp/report/2026");
print "ready\n" if -d "/tmp/report/2026";
remove_tree("/tmp/report/2026");
perl demo.pl
ready
Path::Tiny is the modern alternative that wraps all of this in one small object, and it is the module most new Perl code uses. Lesson 32 explains how to install it from CPAN.
Next: die, warn and eval
Article author: Arthur Isaev