ファイル作成時,指定パスの存在を確認し,ディレクトリが存在しない場合に根元に近い既存ディレクトリからディレクトリを新規作成してパスを構築していくための処理。
● perl の場合
関数再帰呼び出しでパラメータのふるまいがおかしかったのでメモ。
こんな関数を作ったのだが……。
sub mkdirRc { return( ( -d $_[0] )|| ( $_[0] =~ /\/[^\/]+$/ && mkdirRc( $` ) && mkdir( $_[0], 0777 ) ) ); }
受け取ったパラメータのパスが既存なら真を返し(2行め),存在しなければ,最後のスラッシュより前の文字列,つまり親ディレクトリのパスを再帰的に自分に渡して再調査(3行め)をしてから,受け取ったパラメータ名でディレクトリを作る(4行め)。途中で何かエラーがあれば,ディレクトリは作られず偽を返す。
なかなかシンプルに書けたと思っていたが,正しく動作しない。途中で「File exists」というエラーが出る。つまり,存在しないディレクトリでも,「既に存在している(から作れない)」エラーが出る。
調べたところ,親ディレクトリを辿っていき,存在するディレクトリに行き着くと再帰呼び出しから返って来た時のパラメータ($_[0])が全てそのディレクトリ名になってしまうという現象が起きていた。だから,それ以降は既存ディレクトリ名で mkdir が呼び出されるらしい。
たとえば,このサブルーチンでファイルを作るためにパスを構築したい時は以下のように呼び出すわけだが……。
$filname = "/home/user/dir1/dir2/file"; $filname =~ /\/[^\/]+$/; mkdirRc( $` );
/home/user が既存の場合,親ディレクトリを辿ってそこに行き着くと,そこから返って来た時は呼び出した側の $_[0] も /home/user になってしまっていて,mkdir で「既に存在する」エラーが出てしまう。
こうしたら出なくなった。
sub mkdirRc { my $p = $_[0]; return( ( -d $p )|| ( $p =~ /\/[^\/]+$/ && mkdirRc( $` ) && mkdir( $p, 0777 ) ) ); }
1行めの my $p に値を移しただけなのだが。パラメータ配列(@_)というのは,そのサブルーチン「唯一」のものなのか?
そのワリに,以下の「階乗」を求める関数は正常に動作する。
sub fact { return $_[0] ?( fact( $_[0]- 1 )* $_[0] ): 1; }
どういう現象なんだろ。