You want to extract a filename, its enclosing directory, or the extension(s) from a string that contains a full pathname.
Use routines from the standard File::Basename module.
use File::Basename; $base = basename($path); $dir = dirname($path); ($base, $dir, $ext) = fileparse($path);
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 be used to extract the extension. To do so, pass
fileparse
the path to decipher and a regular expression that matches the extension. You must give
fileparse
this 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 of these 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 looking at the
$^O
variable, which holds a string identifying the system 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 wanted just
".bak"
returned, use
'\..*?'
as the second argument to
fileparse
.
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
"."
.
The documentation for the standard File::Basename module (also in
Chapter 7
of
Programming Perl
); the entry for
$^O
in
perlvar
(1), and in the
"Special Variables"
section of
Chapter 2
of
Programming Perl