1*0Sstevel@tonic-gatepackage File::Basename; 2*0Sstevel@tonic-gate 3*0Sstevel@tonic-gate=head1 NAME 4*0Sstevel@tonic-gate 5*0Sstevel@tonic-gatefileparse - split a pathname into pieces 6*0Sstevel@tonic-gate 7*0Sstevel@tonic-gatebasename - extract just the filename from a path 8*0Sstevel@tonic-gate 9*0Sstevel@tonic-gatedirname - extract just the directory from a path 10*0Sstevel@tonic-gate 11*0Sstevel@tonic-gate=head1 SYNOPSIS 12*0Sstevel@tonic-gate 13*0Sstevel@tonic-gate use File::Basename; 14*0Sstevel@tonic-gate 15*0Sstevel@tonic-gate ($name,$path,$suffix) = fileparse($fullname,@suffixlist) 16*0Sstevel@tonic-gate fileparse_set_fstype($os_string); 17*0Sstevel@tonic-gate $basename = basename($fullname,@suffixlist); 18*0Sstevel@tonic-gate $dirname = dirname($fullname); 19*0Sstevel@tonic-gate 20*0Sstevel@tonic-gate ($name,$path,$suffix) = fileparse("lib/File/Basename.pm",qr{\.pm}); 21*0Sstevel@tonic-gate fileparse_set_fstype("VMS"); 22*0Sstevel@tonic-gate $basename = basename("lib/File/Basename.pm",".pm"); 23*0Sstevel@tonic-gate $dirname = dirname("lib/File/Basename.pm"); 24*0Sstevel@tonic-gate 25*0Sstevel@tonic-gate=head1 DESCRIPTION 26*0Sstevel@tonic-gate 27*0Sstevel@tonic-gateThese routines allow you to parse file specifications into useful 28*0Sstevel@tonic-gatepieces using the syntax of different operating systems. 29*0Sstevel@tonic-gate 30*0Sstevel@tonic-gate=over 4 31*0Sstevel@tonic-gate 32*0Sstevel@tonic-gate=item fileparse_set_fstype 33*0Sstevel@tonic-gate 34*0Sstevel@tonic-gateYou select the syntax via the routine fileparse_set_fstype(). 35*0Sstevel@tonic-gate 36*0Sstevel@tonic-gateIf the argument passed to it contains one of the substrings 37*0Sstevel@tonic-gate"VMS", "MSDOS", "MacOS", "AmigaOS" or "MSWin32", the file specification 38*0Sstevel@tonic-gatesyntax of that operating system is used in future calls to 39*0Sstevel@tonic-gatefileparse(), basename(), and dirname(). If it contains none of 40*0Sstevel@tonic-gatethese substrings, Unix syntax is used. This pattern matching is 41*0Sstevel@tonic-gatecase-insensitive. If you've selected VMS syntax, and the file 42*0Sstevel@tonic-gatespecification you pass to one of these routines contains a "/", 43*0Sstevel@tonic-gatethey assume you are using Unix emulation and apply the Unix syntax 44*0Sstevel@tonic-gaterules instead, for that function call only. 45*0Sstevel@tonic-gate 46*0Sstevel@tonic-gateIf the argument passed to it contains one of the substrings "VMS", 47*0Sstevel@tonic-gate"MSDOS", "MacOS", "AmigaOS", "os2", "MSWin32" or "RISCOS", then the pattern 48*0Sstevel@tonic-gatematching for suffix removal is performed without regard for case, 49*0Sstevel@tonic-gatesince those systems are not case-sensitive when opening existing files 50*0Sstevel@tonic-gate(though some of them preserve case on file creation). 51*0Sstevel@tonic-gate 52*0Sstevel@tonic-gateIf you haven't called fileparse_set_fstype(), the syntax is chosen 53*0Sstevel@tonic-gateby examining the builtin variable C<$^O> according to these rules. 54*0Sstevel@tonic-gate 55*0Sstevel@tonic-gate=item fileparse 56*0Sstevel@tonic-gate 57*0Sstevel@tonic-gateThe fileparse() routine divides a file specification into three 58*0Sstevel@tonic-gateparts: a leading B<path>, a file B<name>, and a B<suffix>. The 59*0Sstevel@tonic-gateB<path> contains everything up to and including the last directory 60*0Sstevel@tonic-gateseparator in the input file specification. The remainder of the input 61*0Sstevel@tonic-gatefile specification is then divided into B<name> and B<suffix> based on 62*0Sstevel@tonic-gatethe optional patterns you specify in C<@suffixlist>. Each element of 63*0Sstevel@tonic-gatethis list can be a qr-quoted pattern (or a string which is interpreted 64*0Sstevel@tonic-gateas a regular expression), and is matched 65*0Sstevel@tonic-gateagainst the end of B<name>. If this succeeds, the matching portion of 66*0Sstevel@tonic-gateB<name> is removed and prepended to B<suffix>. By proper use of 67*0Sstevel@tonic-gateC<@suffixlist>, you can remove file types or versions for examination. 68*0Sstevel@tonic-gate 69*0Sstevel@tonic-gateYou are guaranteed that if you concatenate B<path>, B<name>, and 70*0Sstevel@tonic-gateB<suffix> together in that order, the result will denote the same 71*0Sstevel@tonic-gatefile as the input file specification. 72*0Sstevel@tonic-gate 73*0Sstevel@tonic-gate=back 74*0Sstevel@tonic-gate 75*0Sstevel@tonic-gate=head1 EXAMPLES 76*0Sstevel@tonic-gate 77*0Sstevel@tonic-gateUsing Unix file syntax: 78*0Sstevel@tonic-gate 79*0Sstevel@tonic-gate ($base,$path,$type) = fileparse('/virgil/aeneid/draft.book7', 80*0Sstevel@tonic-gate qr{\.book\d+}); 81*0Sstevel@tonic-gate 82*0Sstevel@tonic-gatewould yield 83*0Sstevel@tonic-gate 84*0Sstevel@tonic-gate $base eq 'draft' 85*0Sstevel@tonic-gate $path eq '/virgil/aeneid/', 86*0Sstevel@tonic-gate $type eq '.book7' 87*0Sstevel@tonic-gate 88*0Sstevel@tonic-gateSimilarly, using VMS syntax: 89*0Sstevel@tonic-gate 90*0Sstevel@tonic-gate ($name,$dir,$type) = fileparse('Doc_Root:[Help]Rhetoric.Rnh', 91*0Sstevel@tonic-gate qr{\..*}); 92*0Sstevel@tonic-gate 93*0Sstevel@tonic-gatewould yield 94*0Sstevel@tonic-gate 95*0Sstevel@tonic-gate $name eq 'Rhetoric' 96*0Sstevel@tonic-gate $dir eq 'Doc_Root:[Help]' 97*0Sstevel@tonic-gate $type eq '.Rnh' 98*0Sstevel@tonic-gate 99*0Sstevel@tonic-gate=over 100*0Sstevel@tonic-gate 101*0Sstevel@tonic-gate=item C<basename> 102*0Sstevel@tonic-gate 103*0Sstevel@tonic-gateThe basename() routine returns the first element of the list produced 104*0Sstevel@tonic-gateby calling fileparse() with the same arguments, except that it always 105*0Sstevel@tonic-gatequotes metacharacters in the given suffixes. It is provided for 106*0Sstevel@tonic-gateprogrammer compatibility with the Unix shell command basename(1). 107*0Sstevel@tonic-gate 108*0Sstevel@tonic-gate=item C<dirname> 109*0Sstevel@tonic-gate 110*0Sstevel@tonic-gateThe dirname() routine returns the directory portion of the input file 111*0Sstevel@tonic-gatespecification. When using VMS or MacOS syntax, this is identical to the 112*0Sstevel@tonic-gatesecond element of the list produced by calling fileparse() with the same 113*0Sstevel@tonic-gateinput file specification. (Under VMS, if there is no directory information 114*0Sstevel@tonic-gatein the input file specification, then the current default device and 115*0Sstevel@tonic-gatedirectory are returned.) When using Unix or MSDOS syntax, the return 116*0Sstevel@tonic-gatevalue conforms to the behavior of the Unix shell command dirname(1). This 117*0Sstevel@tonic-gateis usually the same as the behavior of fileparse(), but differs in some 118*0Sstevel@tonic-gatecases. For example, for the input file specification F<lib/>, fileparse() 119*0Sstevel@tonic-gateconsiders the directory name to be F<lib/>, while dirname() considers the 120*0Sstevel@tonic-gatedirectory name to be F<.>). 121*0Sstevel@tonic-gate 122*0Sstevel@tonic-gate=back 123*0Sstevel@tonic-gate 124*0Sstevel@tonic-gate=cut 125*0Sstevel@tonic-gate 126*0Sstevel@tonic-gate 127*0Sstevel@tonic-gate## use strict; 128*0Sstevel@tonic-gate# A bit of juggling to insure that C<use re 'taint';> always works, since 129*0Sstevel@tonic-gate# File::Basename is used during the Perl build, when the re extension may 130*0Sstevel@tonic-gate# not be available. 131*0Sstevel@tonic-gateBEGIN { 132*0Sstevel@tonic-gate unless (eval { require re; }) 133*0Sstevel@tonic-gate { eval ' sub re::import { $^H |= 0x00100000; } ' } # HINT_RE_TAINT 134*0Sstevel@tonic-gate import re 'taint'; 135*0Sstevel@tonic-gate} 136*0Sstevel@tonic-gate 137*0Sstevel@tonic-gate 138*0Sstevel@tonic-gate 139*0Sstevel@tonic-gateuse 5.006; 140*0Sstevel@tonic-gateuse warnings; 141*0Sstevel@tonic-gateour(@ISA, @EXPORT, $VERSION, $Fileparse_fstype, $Fileparse_igncase); 142*0Sstevel@tonic-gaterequire Exporter; 143*0Sstevel@tonic-gate@ISA = qw(Exporter); 144*0Sstevel@tonic-gate@EXPORT = qw(fileparse fileparse_set_fstype basename dirname); 145*0Sstevel@tonic-gate$VERSION = "2.72"; 146*0Sstevel@tonic-gate 147*0Sstevel@tonic-gate 148*0Sstevel@tonic-gate# fileparse_set_fstype() - specify OS-based rules used in future 149*0Sstevel@tonic-gate# calls to routines in this package 150*0Sstevel@tonic-gate# 151*0Sstevel@tonic-gate# Currently recognized values: VMS, MSDOS, MacOS, AmigaOS, os2, RISCOS 152*0Sstevel@tonic-gate# Any other name uses Unix-style rules and is case-sensitive 153*0Sstevel@tonic-gate 154*0Sstevel@tonic-gatesub fileparse_set_fstype { 155*0Sstevel@tonic-gate my @old = ($Fileparse_fstype, $Fileparse_igncase); 156*0Sstevel@tonic-gate if (@_) { 157*0Sstevel@tonic-gate $Fileparse_fstype = $_[0]; 158*0Sstevel@tonic-gate $Fileparse_igncase = ($_[0] =~ /^(?:MacOS|VMS|AmigaOS|os2|RISCOS|MSWin32|MSDOS)/i); 159*0Sstevel@tonic-gate } 160*0Sstevel@tonic-gate wantarray ? @old : $old[0]; 161*0Sstevel@tonic-gate} 162*0Sstevel@tonic-gate 163*0Sstevel@tonic-gate# fileparse() - parse file specification 164*0Sstevel@tonic-gate# 165*0Sstevel@tonic-gate# Version 2.4 27-Sep-1996 Charles Bailey bailey@genetics.upenn.edu 166*0Sstevel@tonic-gate 167*0Sstevel@tonic-gate 168*0Sstevel@tonic-gatesub fileparse { 169*0Sstevel@tonic-gate my($fullname,@suffices) = @_; 170*0Sstevel@tonic-gate unless (defined $fullname) { 171*0Sstevel@tonic-gate require Carp; 172*0Sstevel@tonic-gate Carp::croak("fileparse(): need a valid pathname"); 173*0Sstevel@tonic-gate } 174*0Sstevel@tonic-gate my($fstype,$igncase) = ($Fileparse_fstype, $Fileparse_igncase); 175*0Sstevel@tonic-gate my($dirpath,$tail,$suffix,$basename); 176*0Sstevel@tonic-gate my($taint) = substr($fullname,0,0); # Is $fullname tainted? 177*0Sstevel@tonic-gate 178*0Sstevel@tonic-gate if ($fstype =~ /^VMS/i) { 179*0Sstevel@tonic-gate if ($fullname =~ m#/#) { $fstype = '' } # We're doing Unix emulation 180*0Sstevel@tonic-gate else { 181*0Sstevel@tonic-gate ($dirpath,$basename) = ($fullname =~ /^(.*[:>\]])?(.*)/s); 182*0Sstevel@tonic-gate $dirpath ||= ''; # should always be defined 183*0Sstevel@tonic-gate } 184*0Sstevel@tonic-gate } 185*0Sstevel@tonic-gate if ($fstype =~ /^MS(DOS|Win32)|epoc/i) { 186*0Sstevel@tonic-gate ($dirpath,$basename) = ($fullname =~ /^((?:.*[:\\\/])?)(.*)/s); 187*0Sstevel@tonic-gate $dirpath .= '.\\' unless $dirpath =~ /[\\\/]\z/; 188*0Sstevel@tonic-gate } 189*0Sstevel@tonic-gate elsif ($fstype =~ /^os2/i) { 190*0Sstevel@tonic-gate ($dirpath,$basename) = ($fullname =~ m#^((?:.*[:\\/])?)(.*)#s); 191*0Sstevel@tonic-gate $dirpath = './' unless $dirpath; # Can't be 0 192*0Sstevel@tonic-gate $dirpath .= '/' unless $dirpath =~ m#[\\/]\z#; 193*0Sstevel@tonic-gate } 194*0Sstevel@tonic-gate elsif ($fstype =~ /^MacOS/si) { 195*0Sstevel@tonic-gate ($dirpath,$basename) = ($fullname =~ /^(.*:)?(.*)/s); 196*0Sstevel@tonic-gate $dirpath = ':' unless $dirpath; 197*0Sstevel@tonic-gate } 198*0Sstevel@tonic-gate elsif ($fstype =~ /^AmigaOS/i) { 199*0Sstevel@tonic-gate ($dirpath,$basename) = ($fullname =~ /(.*[:\/])?(.*)/s); 200*0Sstevel@tonic-gate $dirpath = './' unless $dirpath; 201*0Sstevel@tonic-gate } 202*0Sstevel@tonic-gate elsif ($fstype !~ /^VMS/i) { # default to Unix 203*0Sstevel@tonic-gate ($dirpath,$basename) = ($fullname =~ m#^(.*/)?(.*)#s); 204*0Sstevel@tonic-gate if ($^O eq 'VMS' and $fullname =~ m:^(/[^/]+/000000(/|$))(.*):) { 205*0Sstevel@tonic-gate # dev:[000000] is top of VMS tree, similar to Unix '/' 206*0Sstevel@tonic-gate # so strip it off and treat the rest as "normal" 207*0Sstevel@tonic-gate my $devspec = $1; 208*0Sstevel@tonic-gate my $remainder = $3; 209*0Sstevel@tonic-gate ($dirpath,$basename) = ($remainder =~ m#^(.*/)?(.*)#s); 210*0Sstevel@tonic-gate $dirpath ||= ''; # should always be defined 211*0Sstevel@tonic-gate $dirpath = $devspec.$dirpath; 212*0Sstevel@tonic-gate } 213*0Sstevel@tonic-gate $dirpath = './' unless $dirpath; 214*0Sstevel@tonic-gate } 215*0Sstevel@tonic-gate 216*0Sstevel@tonic-gate if (@suffices) { 217*0Sstevel@tonic-gate $tail = ''; 218*0Sstevel@tonic-gate foreach $suffix (@suffices) { 219*0Sstevel@tonic-gate my $pat = ($igncase ? '(?i)' : '') . "($suffix)\$"; 220*0Sstevel@tonic-gate if ($basename =~ s/$pat//s) { 221*0Sstevel@tonic-gate $taint .= substr($suffix,0,0); 222*0Sstevel@tonic-gate $tail = $1 . $tail; 223*0Sstevel@tonic-gate } 224*0Sstevel@tonic-gate } 225*0Sstevel@tonic-gate } 226*0Sstevel@tonic-gate 227*0Sstevel@tonic-gate $tail .= $taint if defined $tail; # avoid warning if $tail == undef 228*0Sstevel@tonic-gate wantarray ? ($basename .= $taint, $dirpath .= $taint, $tail) 229*0Sstevel@tonic-gate : ($basename .= $taint); 230*0Sstevel@tonic-gate} 231*0Sstevel@tonic-gate 232*0Sstevel@tonic-gate 233*0Sstevel@tonic-gate# basename() - returns first element of list returned by fileparse() 234*0Sstevel@tonic-gate 235*0Sstevel@tonic-gatesub basename { 236*0Sstevel@tonic-gate my($name) = shift; 237*0Sstevel@tonic-gate (fileparse($name, map("\Q$_\E",@_)))[0]; 238*0Sstevel@tonic-gate} 239*0Sstevel@tonic-gate 240*0Sstevel@tonic-gate 241*0Sstevel@tonic-gate# dirname() - returns device and directory portion of file specification 242*0Sstevel@tonic-gate# Behavior matches that of Unix dirname(1) exactly for Unix and MSDOS 243*0Sstevel@tonic-gate# filespecs except for names ending with a separator, e.g., "/xx/yy/". 244*0Sstevel@tonic-gate# This differs from the second element of the list returned 245*0Sstevel@tonic-gate# by fileparse() in that the trailing '/' (Unix) or '\' (MSDOS) (and 246*0Sstevel@tonic-gate# the last directory name if the filespec ends in a '/' or '\'), is lost. 247*0Sstevel@tonic-gate 248*0Sstevel@tonic-gatesub dirname { 249*0Sstevel@tonic-gate my($basename,$dirname) = fileparse($_[0]); 250*0Sstevel@tonic-gate my($fstype) = $Fileparse_fstype; 251*0Sstevel@tonic-gate 252*0Sstevel@tonic-gate if ($fstype =~ /VMS/i) { 253*0Sstevel@tonic-gate if ($_[0] =~ m#/#) { $fstype = '' } 254*0Sstevel@tonic-gate else { return $dirname || $ENV{DEFAULT} } 255*0Sstevel@tonic-gate } 256*0Sstevel@tonic-gate if ($fstype =~ /MacOS/i) { 257*0Sstevel@tonic-gate if( !length($basename) && $dirname !~ /^[^:]+:\z/) { 258*0Sstevel@tonic-gate $dirname =~ s/([^:]):\z/$1/s; 259*0Sstevel@tonic-gate ($basename,$dirname) = fileparse $dirname; 260*0Sstevel@tonic-gate } 261*0Sstevel@tonic-gate $dirname .= ":" unless $dirname =~ /:\z/; 262*0Sstevel@tonic-gate } 263*0Sstevel@tonic-gate elsif ($fstype =~ /MS(DOS|Win32)|os2/i) { 264*0Sstevel@tonic-gate $dirname =~ s/([^:])[\\\/]*\z/$1/; 265*0Sstevel@tonic-gate unless( length($basename) ) { 266*0Sstevel@tonic-gate ($basename,$dirname) = fileparse $dirname; 267*0Sstevel@tonic-gate $dirname =~ s/([^:])[\\\/]*\z/$1/; 268*0Sstevel@tonic-gate } 269*0Sstevel@tonic-gate } 270*0Sstevel@tonic-gate elsif ($fstype =~ /AmigaOS/i) { 271*0Sstevel@tonic-gate if ( $dirname =~ /:\z/) { return $dirname } 272*0Sstevel@tonic-gate chop $dirname; 273*0Sstevel@tonic-gate $dirname =~ s#[^:/]+\z## unless length($basename); 274*0Sstevel@tonic-gate } 275*0Sstevel@tonic-gate else { 276*0Sstevel@tonic-gate $dirname =~ s:(.)/*\z:$1:s; 277*0Sstevel@tonic-gate unless( length($basename) ) { 278*0Sstevel@tonic-gate local($File::Basename::Fileparse_fstype) = $fstype; 279*0Sstevel@tonic-gate ($basename,$dirname) = fileparse $dirname; 280*0Sstevel@tonic-gate $dirname =~ s:(.)/*\z:$1:s; 281*0Sstevel@tonic-gate } 282*0Sstevel@tonic-gate } 283*0Sstevel@tonic-gate 284*0Sstevel@tonic-gate $dirname; 285*0Sstevel@tonic-gate} 286*0Sstevel@tonic-gate 287*0Sstevel@tonic-gatefileparse_set_fstype $^O; 288*0Sstevel@tonic-gate 289*0Sstevel@tonic-gate1; 290