Does File::Basename::dirname always return the parent or root directory when the argument is an absolute pathname?
Question
Are there situations where this subroutine - called with a valid path which is not the root directory - does not return the parent directory?
use Cwd qw( realpath );
use File::Basename qw( dirname );
sub parent_dir {
my $dir = realpath shift;
return dirname $dir;
}
Solution
The File::Basename
documentation mentions this caveat:
dirname
This function is provided for compatibility with the Unix shell command
dirname(1)
and has inherited some of its quirks. In spite of its name it does NOT always return the directory name as you might expect. To be safe, if you want the directory name of a path usefileparse()
.
A few examples are presented which makes this clear:
+----------------+-----------+---------------+
| Test Path | dirname() | fileparse() |
+----------------+-----------+---------------+
| /foo/bar/baz | /foo/bar | /foo/bar/ | # dirname() works as expected
+----------------+-----------+---------------+
| /foo/bar/baz/ | /foo/bar | /foo/bar/baz/ | # Should have included baz here
+----------------+-----------+---------------+
| foo/ | . | foo/ | # fileparse() wins again
+----------------+-----------+---------------+
If absolute paths for simple directories and filepaths (without trailing slashes) are provided, the path is similar to the first test, which means that the parent directory is always returned.