次のような関数がありますか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"
基本的に、繰り返しcding の結果となるディレクトリを返します。
次のような関数がありますか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"
基本的に、繰り返しcding の結果となるディレクトリを返します。
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;