1 package File::Spec::Unix;
7 my $xs_version = $VERSION;
10 #dont try to load XSLoader and DynaLoader only to ultimately fail on miniperl
11 if(!defined &canonpath && defined &DynaLoader::boot_DynaLoader) {
12 eval {#eval is questionable since we are handling potential errors like
13 #"Cwd object version 3.48 does not match bootstrap parameter 3.50
14 #at lib/DynaLoader.pm line 216." by having this eval
17 XSLoader::load("Cwd", $xs_version);
26 File::Spec::Unix - File::Spec for Unix, base for other File::Spec modules
30 require File::Spec::Unix; # Done automatically by File::Spec
34 Methods for manipulating file specifications. Other File::Spec
35 modules, such as File::Spec::Mac, inherit from File::Spec::Unix and
36 override specific methods.
44 No physical check on the filesystem, but a logical cleanup of a
45 path. On UNIX eliminates successive slashes and successive "/.".
47 $cpath = File::Spec->canonpath( $path ) ;
49 Note that this does *not* collapse F<x/../y> sections into F<y>. This
50 is by design. If F</foo> on your system is a symlink to F</bar/baz>,
51 then F</foo/../quux> is actually F</bar/quux>, not F</quux> as a naive
52 F<../>-removal would give you. If you want to do this kind of
53 processing, you probably want C<Cwd>'s C<realpath()> function to
54 actually traverse the filesystem cleaning up paths like this.
59 my ($self,$path) = @_;
60 return unless defined $path;
62 # Handle POSIX-style node names beginning with double slash (qnx, nto)
63 # (POSIX says: "a pathname that begins with two successive slashes
64 # may be interpreted in an implementation-defined manner, although
65 # more than two leading slashes shall be treated as a single slash.")
67 my $double_slashes_special = $^O eq 'qnx' || $^O eq 'nto';
70 if ( $double_slashes_special
71 && ( $path =~ s{^(//[^/]+)/?\z}{}s || $path =~ s{^(//[^/]+)/}{/}s ) ) {
75 # $path =~ s|/+|/|g unless ($^O eq 'cygwin');
76 # but that made tests 29, 30, 35, 46, and 213 (as of #13272) to fail
77 # (Mainly because trailing "" directories didn't get stripped).
78 # Why would cygwin avoid collapsing multiple slashes into one? --jhi
79 $path =~ s|/{2,}|/|g; # xx////xx -> xx/xx
80 $path =~ s{(?:/\.)+(?:/|\z)}{/}g; # xx/././xx -> xx/xx
81 $path =~ s|^(?:\./)+||s unless $path eq "./"; # ./xx -> xx
82 $path =~ s|^/(?:\.\./)+|/|; # /../../xx -> xx
83 $path =~ s|^/\.\.$|/|; # /.. -> /
84 $path =~ s|/\z|| unless $path eq "/"; # xx/ -> xx
87 *canonpath = \&_pp_canonpath unless defined &canonpath;
91 Concatenate two or more directory names to form a complete path ending
92 with a directory. But remove the trailing slash from the resulting
93 string, because it doesn't look good, isn't necessary and confuses
94 OS2. Of course, if this is the root directory, don't cut off the
102 $self->canonpath(join('/', @_, '')); # '' because need a trailing '/'
104 *catdir = \&_pp_catdir unless defined &catdir;
108 Concatenate one or more directory names and a filename to form a
109 complete path ending with a filename
115 my $file = $self->canonpath(pop @_);
116 return $file unless @_;
117 my $dir = $self->catdir(@_);
118 $dir .= "/" unless substr($dir,-1) eq "/";
121 *catfile = \&_pp_catfile unless defined &catfile;
125 Returns a string representation of the current directory. "." on UNIX.
130 use constant _fn_curdir => ".";
134 Returns a string representation of the null device. "/dev/null" on UNIX.
138 sub devnull { '/dev/null' }
139 use constant _fn_devnull => "/dev/null";
143 Returns a string representation of the root directory. "/" on UNIX.
148 use constant _fn_rootdir => "/";
152 Returns a string representation of the first writable directory from
153 the following list or the current directory if none from the list are
159 If running under taint mode, and if $ENV{TMPDIR}
160 is tainted, it is not used.
164 my ($tmpdir, %tmpenv);
165 # Cache and return the calculated tmpdir, recording which env vars
168 @tmpenv{@_[2..$#_]} = @ENV{@_[2..$#_]};
169 return $tmpdir = $_[1];
171 # Retrieve the cached tmpdir, checking first whether relevant env vars have
172 # changed and invalidated the cache.
176 return if grep $ENV{$_} ne $tmpenv{$_}, @_;
182 my $taint = do { no strict 'refs'; ${"\cTAINT"} };
183 if ($taint) { # Check for taint mode on perl >= 5.8.0
184 require Scalar::Util;
185 @dirlist = grep { ! Scalar::Util::tainted($_) } @dirlist;
187 elsif ($] < 5.007) { # No ${^TAINT} before 5.8
188 @dirlist = grep { eval { eval('1'.substr $_,0,0) } } @dirlist;
192 next unless defined && -d && -w _;
196 $tmpdir = $self->curdir unless defined $tmpdir;
197 $tmpdir = defined $tmpdir && $self->canonpath($tmpdir);
198 if ( !$self->file_name_is_absolute($tmpdir) ) {
199 # See [perl #120593] for the full details
200 # If possible, return a full path, rather than '.' or 'lib', but
201 # jump through some hoops to avoid returning a tainted value.
203 $taint ? ! Scalar::Util::tainted($_) :
204 $] < 5.007 ? eval { eval('1'.substr $_,0,0) } : 1
205 } $self->rel2abs($tmpdir), $tmpdir;
211 my $cached = $_[0]->_cached_tmpdir('TMPDIR');
212 return $cached if defined $cached;
213 $_[0]->_cache_tmpdir($_[0]->_tmpdir( $ENV{TMPDIR}, "/tmp" ), 'TMPDIR');
218 Returns a string representation of the parent directory. ".." on UNIX.
223 use constant _fn_updir => "..";
227 Given a list of file names, strip out those that refer to a parent
228 directory. (Does not strip symlinks, only '.', '..', and equivalents.)
234 return grep(!/^\.{1,2}\z/s, @_);
239 Returns a true or false value indicating, respectively, that alphabetic
240 is not or is significant when comparing file specifications.
244 sub case_tolerant { 0 }
245 use constant _fn_case_tolerant => 0;
247 =item file_name_is_absolute
249 Takes as argument a path and returns true if it is an absolute path.
251 This does not consult the local filesystem on Unix, Win32, OS/2 or Mac
252 OS (Classic). It does consult the working environment for VMS (see
253 L<File::Spec::VMS/file_name_is_absolute>).
257 sub file_name_is_absolute {
258 my ($self,$file) = @_;
259 return scalar($file =~ m:^/:s);
264 Takes no argument, returns the environment variable PATH as an array.
269 return () unless exists $ENV{PATH};
270 my @path = split(':', $ENV{PATH});
271 foreach (@path) { $_ = '.' if $_ eq '' }
277 join is the same as catfile.
283 return $self->catfile(@_);
288 ($volume,$directories,$file) = File::Spec->splitpath( $path );
289 ($volume,$directories,$file) = File::Spec->splitpath( $path,
292 Splits a path into volume, directory, and filename portions. On systems
293 with no concept of volume, returns '' for volume.
295 For systems with no syntax differentiating filenames from directories,
296 assumes that the last file is a path unless $no_file is true or a
297 trailing separator or /. or /.. is present. On Unix this means that $no_file
298 true makes this return ( '', $path, '' ).
300 The directory portion may or may not be returned with a trailing '/'.
302 The results can be passed to L</catpath()> to get back a path equivalent to
303 (usually identical to) the original path.
308 my ($self,$path, $nofile) = @_;
310 my ($volume,$directory,$file) = ('','','');
316 $path =~ m|^ ( (?: .* / (?: \.\.?\z )? )? ) ([^/]*) |xs;
321 return ($volume,$directory,$file);
327 The opposite of L</catdir()>.
329 @dirs = File::Spec->splitdir( $directories );
331 $directories must be only the directory portion of the path on systems
332 that have the concept of a volume or that have path syntax that differentiates
333 files from directories.
335 Unlike just splitting the directories on the separator, empty
336 directory names (C<''>) can be returned, because these are significant
341 File::Spec->splitdir( "/a/b//c/" );
345 ( '', 'a', 'b', '', 'c', '' )
350 return split m|/|, $_[1], -1; # Preserve trailing fields
356 Takes volume, directory and file portions and returns an entire path. Under
357 Unix, $volume is ignored, and directory and file are concatenated. A '/' is
358 inserted if needed (though if the directory portion doesn't start with
359 '/' it is not added). On other OSs, $volume is significant.
364 my ($self,$volume,$directory,$file) = @_;
366 if ( $directory ne '' &&
368 substr( $directory, -1 ) ne '/' &&
369 substr( $file, 0, 1 ) ne '/'
371 $directory .= "/$file" ;
374 $directory .= $file ;
382 Takes a destination path and an optional base path returns a relative path
383 from the base path to the destination path:
385 $rel_path = File::Spec->abs2rel( $path ) ;
386 $rel_path = File::Spec->abs2rel( $path, $base ) ;
388 If $base is not present or '', then L<cwd()|Cwd> is used. If $base is
389 relative, then it is converted to absolute form using
390 L</rel2abs()>. This means that it is taken to be relative to
393 On systems that have a grammar that indicates filenames, this ignores the
394 $base filename. Otherwise all path components are assumed to be
397 If $path is relative, it is converted to absolute form using L</rel2abs()>.
398 This means that it is taken to be relative to L<cwd()|Cwd>.
400 No checks against the filesystem are made, so the result may not be correct if
401 C<$base> contains symbolic links. (Apply
402 L<Cwd::abs_path()|Cwd/abs_path> beforehand if that
403 is a concern.) On VMS, there is interaction with the working environment, as
404 logicals and macros are expanded.
406 Based on code written by Shigio Yamaguchi.
411 my($self,$path,$base) = @_;
412 $base = $self->_cwd() unless defined $base and length $base;
414 ($path, $base) = map $self->canonpath($_), $path, $base;
416 my $path_directories;
417 my $base_directories;
419 if (grep $self->file_name_is_absolute($_), $path, $base) {
420 ($path, $base) = map $self->rel2abs($_), $path, $base;
422 my ($path_volume) = $self->splitpath($path, 1);
423 my ($base_volume) = $self->splitpath($base, 1);
425 # Can't relativize across volumes
426 return $path unless $path_volume eq $base_volume;
428 $path_directories = ($self->splitpath($path, 1))[1];
429 $base_directories = ($self->splitpath($base, 1))[1];
431 # For UNC paths, the user might give a volume like //foo/bar that
432 # strictly speaking has no directory portion. Treat it as if it
433 # had the root directory for that volume.
434 if (!length($base_directories) and $self->file_name_is_absolute($base)) {
435 $base_directories = $self->rootdir;
439 my $wd= ($self->splitpath($self->_cwd(), 1))[1];
440 $path_directories = $self->catdir($wd, $path);
441 $base_directories = $self->catdir($wd, $base);
444 # Now, remove all leading components that are the same
445 my @pathchunks = $self->splitdir( $path_directories );
446 my @basechunks = $self->splitdir( $base_directories );
448 if ($base_directories eq $self->rootdir) {
449 return $self->curdir if $path_directories eq $self->rootdir;
451 return $self->canonpath( $self->catpath('', $self->catdir( @pathchunks ), '') );
455 while (@pathchunks && @basechunks && $self->_same($pathchunks[0], $basechunks[0])) {
456 push @common, shift @pathchunks ;
459 return $self->curdir unless @pathchunks || @basechunks;
461 # @basechunks now contains the directories the resulting relative path
462 # must ascend out of before it can descend to $path_directory. If there
463 # are updir components, we must descend into the corresponding directories
464 # (this only works if they are no symlinks).
466 while( defined(my $dir= shift @basechunks) ) {
467 if( $dir ne $self->updir ) {
468 unshift @reverse_base, $self->updir;
472 if( @reverse_base && $reverse_base[0] eq $self->updir ) {
477 unshift @reverse_base, pop @common;
481 my $result_dirs = $self->catdir( @reverse_base, @pathchunks );
482 return $self->canonpath( $self->catpath('', $result_dirs, '') );
491 Converts a relative path to an absolute path.
493 $abs_path = File::Spec->rel2abs( $path ) ;
494 $abs_path = File::Spec->rel2abs( $path, $base ) ;
496 If $base is not present or '', then L<cwd()|Cwd> is used. If $base is
497 relative, then it is converted to absolute form using
498 L</rel2abs()>. This means that it is taken to be relative to
501 On systems that have a grammar that indicates filenames, this ignores
502 the $base filename. Otherwise all path components are assumed to be
505 If $path is absolute, it is cleaned up and returned using L</canonpath()>.
507 No checks against the filesystem are made. On VMS, there is
508 interaction with the working environment, as logicals and
511 Based on code written by Shigio Yamaguchi.
516 my ($self,$path,$base ) = @_;
519 if ( ! $self->file_name_is_absolute( $path ) ) {
520 # Figure out the effective $base and clean it up.
521 if ( !defined( $base ) || $base eq '' ) {
522 $base = $self->_cwd();
524 elsif ( ! $self->file_name_is_absolute( $base ) ) {
525 $base = $self->rel2abs( $base ) ;
528 $base = $self->canonpath( $base ) ;
532 $path = $self->catdir( $base, $path ) ;
535 return $self->canonpath( $path ) ;
542 Copyright (c) 2004 by the Perl 5 Porters. All rights reserved.
544 This program is free software; you can redistribute it and/or modify
545 it under the same terms as Perl itself.
547 Please submit bug reports and patches to perlbug@perl.org.
555 # Internal routine to File::Spec, no point in making this public since
556 # it is the standard Cwd interface. Most of the platform-specific
557 # File::Spec subclasses use this.
564 # Internal method to reduce xx\..\yy -> yy
568 my $updir = $fs->updir;
569 my $curdir = $fs->curdir;
571 my($vol, $dirs, $file) = $fs->splitpath($path);
572 my @dirs = $fs->splitdir($dirs);
573 pop @dirs if @dirs && $dirs[-1] eq '';
576 foreach my $dir (@dirs) {
577 if( $dir eq $updir and # if we have an updir
578 @collapsed and # and something to collapse
579 length $collapsed[-1] and # and its not the rootdir
580 $collapsed[-1] ne $updir and # nor another updir
581 $collapsed[-1] ne $curdir # nor the curdir
584 pop @collapsed; # collapse
587 push @collapsed, $dir; # just hang onto it
591 return $fs->catpath($vol,
592 $fs->catdir(@collapsed),