1 package File::Spec::Unix;
10 File::Spec::Unix - File::Spec for Unix, base for other File::Spec modules
14 require File::Spec::Unix; # Done automatically by File::Spec
18 Methods for manipulating file specifications. Other File::Spec
19 modules, such as File::Spec::Mac, inherit from File::Spec::Unix and
20 override specific methods.
28 No physical check on the filesystem, but a logical cleanup of a
29 path. On UNIX eliminates successive slashes and successive "/.".
31 $cpath = File::Spec->canonpath( $path ) ;
33 Note that this does *not* collapse F<x/../y> sections into F<y>. This
34 is by design. If F</foo> on your system is a symlink to F</bar/baz>,
35 then F</foo/../quux> is actually F</bar/quux>, not F</quux> as a naive
36 F<../>-removal would give you. If you want to do this kind of
37 processing, you probably want C<Cwd>'s C<realpath()> function to
38 actually traverse the filesystem cleaning up paths like this.
43 my ($self,$path) = @_;
45 # Handle POSIX-style node names beginning with double slash (qnx, nto)
46 # Handle network path names beginning with double slash (cygwin)
47 # (POSIX says: "a pathname that begins with two successive slashes
48 # may be interpreted in an implementation-defined manner, although
49 # more than two leading slashes shall be treated as a single slash.")
51 my $double_slashes_special = $self->isa("File::Spec::Cygwin") || $^O =~ m/^(?:qnx|nto)$/;
52 if ( $double_slashes_special && $path =~ s:^(//[^/]+)(/|\z):/:s ) {
56 # $path =~ s|/+|/|g unless ($^O eq 'cygwin');
57 # but that made tests 29, 30, 35, 46, and 213 (as of #13272) to fail
58 # (Mainly because trailing "" directories didn't get stripped).
59 # Why would cygwin avoid collapsing multiple slashes into one? --jhi
60 $path =~ s|/+|/|g; # xx////xx -> xx/xx
61 $path =~ s@(/\.)+(/|\Z(?!\n))@/@g; # xx/././xx -> xx/xx
62 $path =~ s|^(\./)+||s unless $path eq "./"; # ./xx -> xx
63 $path =~ s|^/(\.\./)+|/|; # /../../xx -> xx
64 $path =~ s|^/\.\.$|/|; # /.. -> /
65 $path =~ s|/\Z(?!\n)|| unless $path eq "/"; # xx/ -> xx
71 Concatenate two or more directory names to form a complete path ending
72 with a directory. But remove the trailing slash from the resulting
73 string, because it doesn't look good, isn't necessary and confuses
74 OS2. Of course, if this is the root directory, don't cut off the
82 $self->canonpath(join('/', @_, '')); # '' because need a trailing '/'
87 Concatenate one or more directory names and a filename to form a
88 complete path ending with a filename
94 my $file = $self->canonpath(pop @_);
95 return $file unless @_;
96 my $dir = $self->catdir(@_);
97 $dir .= "/" unless substr($dir,-1) eq "/";
103 Returns a string representation of the current directory. "." on UNIX.
107 sub curdir () { '.' }
111 Returns a string representation of the null device. "/dev/null" on UNIX.
115 sub devnull () { '/dev/null' }
119 Returns a string representation of the root directory. "/" on UNIX.
123 sub rootdir () { '/' }
127 Returns a string representation of the first writable directory from
128 the following list or the current directory if none from the list are
134 Since perl 5.8.0, if running under taint mode, and if $ENV{TMPDIR}
135 is tainted, it is not used.
141 return $tmpdir if defined $tmpdir;
146 if (${"\cTAINT"}) { # Check for taint mode on perl >= 5.8.0
147 require Scalar::Util;
148 @dirlist = grep { ! Scalar::Util::tainted($_) } @dirlist;
152 next unless defined && -d && -w _;
156 $tmpdir = $self->curdir unless defined $tmpdir;
157 $tmpdir = defined $tmpdir && $self->canonpath($tmpdir);
162 return $tmpdir if defined $tmpdir;
163 $tmpdir = $_[0]->_tmpdir( $ENV{TMPDIR}, "/tmp" );
168 Returns a string representation of the parent directory. ".." on UNIX.
172 sub updir () { '..' }
176 Given a list of file names, strip out those that refer to a parent
177 directory. (Does not strip symlinks, only '.', '..', and equivalents.)
183 return grep(!/^\.{1,2}\Z(?!\n)/s, @_);
188 Returns a true or false value indicating, respectively, that alphabetic
189 is not or is significant when comparing file specifications.
193 sub case_tolerant () { 0 }
195 =item file_name_is_absolute
197 Takes as argument a path and returns true if it is an absolute path.
199 This does not consult the local filesystem on Unix, Win32, OS/2 or Mac
200 OS (Classic). It does consult the working environment for VMS (see
201 L<File::Spec::VMS/file_name_is_absolute>).
205 sub file_name_is_absolute {
206 my ($self,$file) = @_;
207 return scalar($file =~ m:^/:s);
212 Takes no argument, returns the environment variable PATH as an array.
217 return () unless exists $ENV{PATH};
218 my @path = split(':', $ENV{PATH});
219 foreach (@path) { $_ = '.' if $_ eq '' }
225 join is the same as catfile.
231 return $self->catfile(@_);
236 ($volume,$directories,$file) = File::Spec->splitpath( $path );
237 ($volume,$directories,$file) = File::Spec->splitpath( $path, $no_file );
239 Splits a path into volume, directory, and filename portions. On systems
240 with no concept of volume, returns '' for volume.
242 For systems with no syntax differentiating filenames from directories,
243 assumes that the last file is a path unless $no_file is true or a
244 trailing separator or /. or /.. is present. On Unix this means that $no_file
245 true makes this return ( '', $path, '' ).
247 The directory portion may or may not be returned with a trailing '/'.
249 The results can be passed to L</catpath()> to get back a path equivalent to
250 (usually identical to) the original path.
255 my ($self,$path, $nofile) = @_;
257 my ($volume,$directory,$file) = ('','','');
263 $path =~ m|^ ( (?: .* / (?: \.\.?\Z(?!\n) )? )? ) ([^/]*) |xs;
268 return ($volume,$directory,$file);
274 The opposite of L</catdir()>.
276 @dirs = File::Spec->splitdir( $directories );
278 $directories must be only the directory portion of the path on systems
279 that have the concept of a volume or that have path syntax that differentiates
280 files from directories.
282 Unlike just splitting the directories on the separator, empty
283 directory names (C<''>) can be returned, because these are significant
288 File::Spec->splitdir( "/a/b//c/" );
292 ( '', 'a', 'b', '', 'c', '' )
297 return split m|/|, $_[1], -1; # Preserve trailing fields
303 Takes volume, directory and file portions and returns an entire path. Under
304 Unix, $volume is ignored, and directory and file are concatenated. A '/' is
305 inserted if needed (though if the directory portion doesn't start with
306 '/' it is not added). On other OSs, $volume is significant.
311 my ($self,$volume,$directory,$file) = @_;
313 if ( $directory ne '' &&
315 substr( $directory, -1 ) ne '/' &&
316 substr( $file, 0, 1 ) ne '/'
318 $directory .= "/$file" ;
321 $directory .= $file ;
329 Takes a destination path and an optional base path returns a relative path
330 from the base path to the destination path:
332 $rel_path = File::Spec->abs2rel( $path ) ;
333 $rel_path = File::Spec->abs2rel( $path, $base ) ;
335 If $base is not present or '', then L<cwd()|Cwd> is used. If $base is
336 relative, then it is converted to absolute form using
337 L</rel2abs()>. This means that it is taken to be relative to
340 On systems that have a grammar that indicates filenames, this ignores the
341 $base filename. Otherwise all path components are assumed to be
344 If $path is relative, it is converted to absolute form using L</rel2abs()>.
345 This means that it is taken to be relative to L<cwd()|Cwd>.
347 No checks against the filesystem are made. On VMS, there is
348 interaction with the working environment, as logicals and
351 Based on code written by Shigio Yamaguchi.
356 my($self,$path,$base) = @_;
357 $base = $self->_cwd() unless defined $base and length $base;
359 ($path, $base) = map $self->canonpath($_), $path, $base;
361 if (grep $self->file_name_is_absolute($_), $path, $base) {
362 ($path, $base) = map $self->rel2abs($_), $path, $base;
365 # save a couple of cwd()s if both paths are relative
366 ($path, $base) = map $self->catdir('/', $_), $path, $base;
369 my ($path_volume) = $self->splitpath($path, 1);
370 my ($base_volume) = $self->splitpath($base, 1);
372 # Can't relativize across volumes
373 return $path unless $path_volume eq $base_volume;
375 my $path_directories = ($self->splitpath($path, 1))[1];
376 my $base_directories = ($self->splitpath($base, 1))[1];
378 # For UNC paths, the user might give a volume like //foo/bar that
379 # strictly speaking has no directory portion. Treat it as if it
380 # had the root directory for that volume.
381 if (!length($base_directories) and $self->file_name_is_absolute($base)) {
382 $base_directories = $self->rootdir;
385 # Now, remove all leading components that are the same
386 my @pathchunks = $self->splitdir( $path_directories );
387 my @basechunks = $self->splitdir( $base_directories );
389 if ($base_directories eq $self->rootdir) {
391 return $self->canonpath( $self->catpath('', $self->catdir( @pathchunks ), '') );
394 while (@pathchunks && @basechunks && $self->_same($pathchunks[0], $basechunks[0])) {
398 return $self->curdir unless @pathchunks || @basechunks;
400 # $base now contains the directories the resulting relative path
401 # must ascend out of before it can descend to $path_directory.
402 my $result_dirs = $self->catdir( ($self->updir) x @basechunks, @pathchunks );
403 return $self->canonpath( $self->catpath('', $result_dirs, '') );
412 Converts a relative path to an absolute path.
414 $abs_path = File::Spec->rel2abs( $path ) ;
415 $abs_path = File::Spec->rel2abs( $path, $base ) ;
417 If $base is not present or '', then L<cwd()|Cwd> is used. If $base is
418 relative, then it is converted to absolute form using
419 L</rel2abs()>. This means that it is taken to be relative to
422 On systems that have a grammar that indicates filenames, this ignores
423 the $base filename. Otherwise all path components are assumed to be
426 If $path is absolute, it is cleaned up and returned using L</canonpath()>.
428 No checks against the filesystem are made. On VMS, there is
429 interaction with the working environment, as logicals and
432 Based on code written by Shigio Yamaguchi.
437 my ($self,$path,$base ) = @_;
440 if ( ! $self->file_name_is_absolute( $path ) ) {
441 # Figure out the effective $base and clean it up.
442 if ( !defined( $base ) || $base eq '' ) {
443 $base = $self->_cwd();
445 elsif ( ! $self->file_name_is_absolute( $base ) ) {
446 $base = $self->rel2abs( $base ) ;
449 $base = $self->canonpath( $base ) ;
453 $path = $self->catdir( $base, $path ) ;
456 return $self->canonpath( $path ) ;
463 Copyright (c) 2004 by the Perl 5 Porters. All rights reserved.
465 This program is free software; you can redistribute it and/or modify
466 it under the same terms as Perl itself.
474 # Internal routine to File::Spec, no point in making this public since
475 # it is the standard Cwd interface. Most of the platform-specific
476 # File::Spec subclasses use this.
483 # Internal method to reduce xx\..\yy -> yy
487 my $updir = $fs->updir;
488 my $curdir = $fs->curdir;
490 my($vol, $dirs, $file) = $fs->splitpath($path);
491 my @dirs = $fs->splitdir($dirs);
492 pop @dirs if @dirs && $dirs[-1] eq '';
495 foreach my $dir (@dirs) {
496 if( $dir eq $updir and # if we have an updir
497 @collapsed and # and something to collapse
498 length $collapsed[-1] and # and its not the rootdir
499 $collapsed[-1] ne $updir and # nor another updir
500 $collapsed[-1] ne $curdir # nor the curdir
503 pop @collapsed; # collapse
506 push @collapsed, $dir; # just hang onto it
510 return $fs->catpath($vol,
511 $fs->catdir(@collapsed),