The documen开发者_开发问答tation for File::Basename says
NOTE: "dirname()" and "basename()" emulate the behaviours, and quirks,
of the shell and C functions of the same name. See each function's
documentation for details.
What are these quirks?
Actually, the quirks are documented in the documentation for the Perl functions themselves. http://search.cpan.org/~rjbs/perl-5.16.0/lib/File/Basename.pm#basename
This function is provided for compatibility with the Unix shell command basename(1). It does NOT always return the file name portion of a path as you might expect. ... basename() returns the last level of a filepath even if the last level is clearly directory. ... Also note that in order to be compatible with the shell command, basename() does not strip off a suffix if it is identical to the remaining characters in the filename.
In other words, basename("dir/")
is "dir/"
, not ""
; and basename("dir/.txt", ".txt")
is ".txt"
, not ""
.
http://search.cpan.org/~rjbs/perl-5.16.0/lib/File/Basename.pm#dirname
The quirks of dirname
are much quirkier, and depend on the current value of $File::Basename::Fileparse_fstype
. I'll just paste the code here, since it's short.
sub dirname {
my $path = shift;
my($type) = $Fileparse_fstype;
if( $type eq 'VMS' and $path =~ m{/} ) {
# Parse as Unix
local($File::Basename::Fileparse_fstype) = '';
return dirname($path);
}
my($basename, $dirname) = fileparse($path);
if ($type eq 'VMS') {
$dirname ||= $ENV{DEFAULT};
} elsif ($type eq 'MacOS') {
if( !length($basename) && $dirname !~ /^[^:]+:\z/) {
_strip_trailing_sep($dirname);
($basename,$dirname) = fileparse $dirname;
}
$dirname .= ":" unless $dirname =~ /:\z/;
} elsif (grep { $type eq $_ } qw(MSDOS DOS MSWin32 OS2)) {
_strip_trailing_sep($dirname);
unless( length($basename) ) {
($basename,$dirname) = fileparse $dirname;
_strip_trailing_sep($dirname);
}
} elsif ($type eq 'AmigaOS') {
if ( $dirname =~ /:\z/) { return $dirname }
chop $dirname;
$dirname =~ s{[^:/]+\z}{} unless length($basename);
} else {
_strip_trailing_sep($dirname);
unless( length($basename) ) {
($basename,$dirname) = fileparse $dirname;
_strip_trailing_sep($dirname);
}
}
$dirname;
}
# Strip the trailing path separator.
sub _strip_trailing_sep {
my $type = $Fileparse_fstype;
if ($type eq 'MacOS') {
$_[0] =~ s/([^:]):\z/$1/s;
} elsif (grep { $type eq $_ } qw(MSDOS DOS MSWin32 OS2)) {
$_[0] =~ s/([^:])[\\\/]*\z/$1/;
} else {
$_[0] =~ s{(.)/*\z}{$1}s;
}
}
The quirks are documented in the man
pages for each function:
man dirname
DESCRIPTION
Print NAME with its trailing /component removed; if NAME contains no /'s, output '.' (meaning the current directory).
EXAMPLES
dirname /usr/bin/sort Output "/usr/bin". dirname stdio.h Output ".".
man basename
DESCRIPTION
Print NAME with any leading directory components removed. If specified, also remove a trailing SUFFIX.
EXAMPLES
basename /usr/bin/sort Output "sort". basename include/stdio.h .h Output "stdio".
精彩评论