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