rel2abs - convert a relative path to an absolute path
realpath - convert a logical path to a physical path (resolve symlinks)
splitpath - split a path in to volume, directory and filename components
joinpath - join volume, directory, and filename components to form a path
splitdirs - split directory specification in to component names
joindirs - join component names in to a directory specification
setfstype - set the file system type
use File::PathConvert qw(realpath abs2rel rel2abs setfstype splitpath joinpath splitdirs joindirs $resolved);
$relpath = abs2rel($abspath); $abspath = abs2rel($abspath, $base);
$abspath = rel2abs($relpath); $abspath = rel2abs($relpath, $base);
$path = realpath($logpath) || die "resolution stopped at $resolved";
( $volume, $directory, $filename )= splitpath( $path ) ; ( $volume, $directory, $filename )= splitpath( $path, 'nofile' ) ;
$path= joinpath( $volume, $directory, $filename ) ;
@directories= splitdirs( $directory ) ; $directory= joindirs( @directories ) ;
Paths are decomposed internally in to volume, directory, and, sometimes filename portions as appropriate to the operation and filesystem, then recombined. This preserves the volume and filename portions so that they may be returned, and prevents them from interfering with the path conversions.
Here are some examples of path decomposition. A '****' in a column indicates the column is not used in abs2rel and rel2abs functions for that filesystem type.
FS VOLUME Directory filename ======= ======================= =============== ============= URL http: /a/b/ c?query http://fubar.com /a/b/ c?query //p.d.q.com /a/b/c/ ?query
VMS Server::Volume: [a.b] c Server"access spec":: [a.b] c Volume: [a.b] c
Win32 A: \a\b\c **** \\server\Volume \a\b\c **** \\server\Volume \a/b/c ****
Unix **** \a\b\c ****
MacOS Volume:: a:b:c ****
Many more examples abound in the test.pl included with this module.
Only the VMS and URL filesystems indicate if the last name in a path is a directory or file. For other filesystems, all non-volume names are assumed to be directory names. For URLs, the last name in a path is assumed to be a filename unless it ends in '/'.
Other assumptions are made as well, especially MacOS and VMS. THESE MAY CHANGE BASED ON PROGRAMMER FEEDBACK!
The conversion routines abs2rel, rel2abs, and realpath are the main focus of this package. splitpath and joinpath are provided to allow volume oriented filesystems (almost anything non-unixian, actually) to be accomodated. splitdirs and joindirs provide directory path grammar parsing and encoding, which is especially useful for VMS.
Examples:
File::PathConvert::setfstype( 'url' ) ; File::PathConvert::setfstype( 'Win32' ) ; File::PathConvert::setfstype( 'HAL9000' ) ; # Results in Unix default
$relpath= abs2rel( $abspath ) ; $relpath= abs2rel( $abspath, $base ) ;
If $abspath
is already relative, it is returned unchanged.
Otherwise the relative path from $base
to
$abspath
is returned. If $base
is undefined the
current directory is used.
The volume and filename portions of $base
are ignored if
present. If $abspath
and $base
are on different
volumes, the volume from $abspath
is used.
No filesystem calls are made except for getting the current working
directory if $base
is undefined, so symbolic links are not
checked for or resolved, and no check is done for existance.
Examples
# Unix 'a/b/c' == abs2rel( 'a/b/c', $anything ) 'a/b/c' == abs2rel( '/1/2/3/a/b/c', '/1/2/3' )
# DOS 'a\\b/c' == abs2rel( 'a\\b/c', $anything ) 'a\\b/c' == abs2rel( '/1\\2/3/a\\b/c', '/1/2/3' )
# URL 'http:a/b/c' == abs2rel( 'http:a/b/c', $anything ) 'http:a/b/c' == abs2rel( 'http:/1/2/3/a/b/c', 'ftp://t.org/1/2/3/?z' ) 'http:a/b/c?q' == abs2rel( 'http:/1/2/3/a/b/c/?q', 'ftp://t.org/1/2/3?z' ) 'http://s.com/a/b/c?q' == abs2rel( 'http://s.com/1/2/3/a/b/c?q', 'ftp://t.org/1/2/3/?z')
$abspath= rel2abs( $relpath ) ; $abspath= rel2abs( $relpath, $base ) ;
If $relpath
is already absolute, it is returned unchanged.
Otherwise $relpath
is taken to be relative to
$base
and the resulting absolute path is returned. If
$base
is not supplied, the current working directory is used.
The volume portion of $relpath
is ignored. The filename
portion of $base
is also ignored. The volume from
$base
is returned if present. The filename portion of
$abspath
is returned if present.
No filesystem calls are made except for getting the current working
directory if $base
is undefined, so symbolic links are not
checked for or resolved, and no check is done for existance.
Examples
# Unix '/a/b/c' == rel2abs( '/a/b/c', $anything ) '/1/2/3/a/b/c' == rel2abs( 'a/b/c', '/1/2/3' )
# DOS '\\a\\b/c' == rel2abs( '\\a\\b/c', $anything ) '/1\\2/3\\a\\b/c' == rel2abs( 'a\\b/c', '/1\\2/3' ) 'C:/1\\2/3\\a\\b/c' == rel2abs( 'D:a\\b/c', 'C:/1\\2/3' ) '\\\\s\\v/1\\2/3\\a\\b/c' == rel2abs( 'D:a\\b/c', '\\\\s\\v/1\\2/3' )
# URL 'http:/a/b/c?q' == rel2abs( 'http:/a/b/c?q', $anything ) 'ftp://t.org/1/2/3/a/b/c?q'== rel2abs( 'http:a/b/c?q', 'ftp://t.org/1/2/3?z' )
$File::PathConvert::resolved
to the pathname that caused the problem.
All but the last component of the path must exist.
This implementation is based on 4.4BSD realpath(3).
It is not
tested under other operating systems at this time.
If '/sys' is a symbolic link to '/usr/src/sys':
chdir('/usr'); '/usr/src/sys/kern' == realpath('../sys/kern'); '/usr/src/sys/kern' == realpath('/sys/kern');