Perlメモ/パスの正規化
ファイルパスの妥当性をチェックするのにまず必要なパスの正規化。
基本的には、「Unixパス名の安全対策」(www.ipa.go.jp)を行なえばよいわけです。 ただ、今回抱えているケースで相対ディレクトリは相対ディレクトリとして正規化したかったので、そのあたりの修正。 というか、実はそれを先に書いた後、そういえばipaのページに同じようなのがあったな、と思い出したのでした。 当然ですが、できるものはほぼ同じになってしまいますね。
パスを正規化するためのサブルーチンは以下のようになります。
sub canonical_path {
my $path = shift;
my @parts = ();
@parts = ('') if ($path =~ /^\//);
foreach my $part (split('/', $path)) {
if ($part eq '..') {
if (@parts == 0) { @parts = ('..'); }
elsif (@parts == 1 and $parts[0] eq '') { return undef; }
elsif ($parts[$#parts] eq '..') { push(@parts, '..'); }
else { pop(@parts); }
} elsif ($part and $part ne '.') {
push(@parts, $part);
}
print qq(\t"$part" -> ).join('/', @parts)."\n";
}
$path = (@parts) ? join('/', @parts) : '.';
return $path;
}
次のように使用します。
my $path = &canonical_path('../dir1/./../../dir2//file');
正規化の過程で、先頭の'./'や末尾の'/'がなくなります。 ただし、正規化の結果が単純に上のルールに従うと、ルートディレクトリとカレントディレクトリはともに''になってしまうので、カレントディレクトリについては'.'を返すようにしています。
処理の流れは次のようになっています。
[[#rcomment]]