I'm using File::Spec on a Unix system to get the absolute path of a file:
use File::Spec::Functions qw(:ALL);
use strict;
use warnings;
use feature qw(say);
my $file = "../../this/is/a/test";
say rel2abs($file);
This prints out /directory/to/program/../../this/is/a/test
. I'd like it to print out /directory/this/is/a/test
.
I saw the no_upwards
method, and here's the description:
Given a list of file names, strip out those that refer to a parent directory.
(Does not strip symlinks, only '.', '..', and equivalents.)
@paths = File::Spec->no_upwards( @paths );
However, this didn't seem to work. Instead, I looked at the code in the File::Spec module and found this:
sub no_upwards {
my $self = shift;
return grep(!/^\.{1,2}\z/s, @_);
}
So, what does this method do, and how do I get it to work?
If I'm reading this right, this takes a list of directories, and then removes all those directories that are .
or ..
. (According to Perldoc \z
means match only at the end of a string).
Is there a platform independent way of collapsing these special directories? What is no_upwards
suppose to do, and how do you use it? I tried:
say no_upwards(rel2abs($file));
Is there another method I should be using?
In the documentation for canonpath in File::Spec, it says:
METHODS
canonpath
No physical check on the filesystem, but a logical cleanup of a path.
$cpath = File::Spec->canonpath( $path ) ;
Note that this does not collapse
x/../y
sections intoy
. This is by design. If/foo
on your system is a symlink to/bar/baz
, then/foo/../quux
is actually/bar/quux
, not/quux
as a naive../
-removal would give you. If you want to do this kind of processing, you probably want Cwd's realpath() function to actually traverse the filesystem cleaning up paths like this.
So I'd look into using Cwd's realpath() function like it says.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With