次のような関数がありますかf
(ベース Perl またはライブラリ内):
f("/a/b/c", "./d") == "/a/b/c/d"
f("/a/b/c", "../d") == "/a/b/d"
f("/a/b/c", "/d") == "/d"
基本的に、繰り返しcd
ing の結果となるディレクトリを返します。
次のような関数がありますかf
(ベース Perl またはライブラリ内):
f("/a/b/c", "./d") == "/a/b/c/d"
f("/a/b/c", "../d") == "/a/b/d"
f("/a/b/c", "/d") == "/d"
基本的に、繰り返しcd
ing の結果となるディレクトリを返します。
Core のFile::Specにはそのような関数 ( ) がありますが、私はPath::Classrel2abs
を好みます ( File::Spec を誤って使用するのは簡単すぎるため)。
use Path::Class qw( dir );
say dir('./d')->absolute('/a/b/c'); # /a/b/c/d
say dir('../d')->absolute('/a/b/c'); # /a/b/d
say dir('/d')->absolute('/a/b/c'); # /d
file
ファイルへのパスを作成する場合の代わりに使用dir
します。
ちなみに、./d
はただの言い回しd
です。
おっと、UNIXシステムでは、ファイルシステムをチェックしないと手段/a/b/c/../d
を知ることができないため、中間のものに戻ります。(実際には./a/b/c/../d
/a/b/d
/a/b/e/f/d
おそらくこれには多くのものが欠けていますが、関数f
は次のようになります。
use warnings;
use strict;
sub f {
my ($s, $cd) = @_;
return $cd if ($cd =~ m!^/!); # return path if abs
$cd =~ s!//+!/!g;
my @v = split(/\//, $cd);
my @i = split(/\//, $s);
for my $c (@v) {
next if $c eq ".";
pop @i, next if $c eq "..";
push @i, $c;
}
return join("/", @i);
}
my @p = (
["/a/b/c", "./d"],
["a/b/c", "../d"],
["/a/b/c/", "/d"],
["a/b/c/e/f/g", "../../c/e/../d"]);
print f(@$_), "\n" for @p;