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