Recipe 9.10 Splitting a Filename into Its Component Parts
9.10.1 Problem
You want to extract a filename, its
enclosing directory, or the extension(s) from a string that contains
a full pathname.
9.10.2 Solution
Use routines from the standard File::Basename
module.
use File::Basename;
$base = basename($path);
$dir = dirname($path);
($base, $dir, $ext) = fileparse($path);
9.10.3 Discussion
The standard File::Basename module
contains routines to split up a filename. dirname
and basename supply the directory and filename
portions, respectively:
$path = "/usr/lib/libc.a";
$file = basename($path);
$dir = dirname($path);
print "dir is $dir, file is $file\n";
# dir is /usr/lib, file is libc.a
The
fileparse function can extract the extension. Pass
fileparse the path to decipher and a regular
expression that matches the extension. You must supply a pattern
because an extension isn't necessarily dot-separated. Consider
".tar.gz": is the extension
".tar", ".gz", or
".tar.gz"? By specifying the pattern, you control
which you get.
$path = "/usr/lib/libc.a";
($name,$dir,$ext) = fileparse($path,'\..*');
print "dir is $dir, name is $name, extension is $ext\n";
# dir is /usr/lib/, name is libc, extension is .a
By default, these routines parse pathnames using your operating
system's normal conventions for directory separators by consulting
the $^O ($OSNAME) variable,
which holds a string identifying the platform you're running on. That
value was determined when Perl was built and installed. You can
change the default by calling the
fileparse_set_fstype routine. This alters the
behavior of subsequent calls to the File::Basename
functions:
fileparse_set_fstype("MacOS");
$path = "Hard%20Drive:System%20Folder:README.txt";
($name,$dir,$ext) = fileparse($path,'\..*');
print "dir is $dir, name is $name, extension is $ext\n";
# dir is Hard%20Drive:System%20Folder, name is README, extension is .txt
To pull out just the extension, you might use this:
sub extension {
my $path = shift;
my $ext = (fileparse($path,'\..*'))[2];
$ext =~ s/^\.//;
return $ext;
}
When called on a file like source.c.bak, this
returns an extension of "c.bak", not just
"bak". If you want ".bak"
returned, use '\.[^.]*' as the second argument to
fileparse (this will, of course, leave the
filename as source.c).
When passed a pathname with a trailing directory separator, such as
"lib/", fileparse considers the
directory name to be "lib/", whereas
dirname considers it to be ".".
9.10.4 See Also
The documentation for the standard File::Basename module (also in
Chapter 32 of Programming Perl); the entry for
$^O ($OSNAME) in
perlvar(1), and in the "Special Variables in
Alphabetical Order" section of Chapter 28 of Programming
Perl
|