ディレクトリの作成と削除1では組み込み関数のmkdirやrmdirを使って単一のディレクトリの作成や削除をする方法を解説しましたが、File::Pathモジュールを使うと、複数のディレクトリを再帰的に一括作成したり、ディレクトリの中のファイルやサブディレクトリをごっそりと一括削除したりできます。
では、まずはディレクトリ作成の簡単なサンプルです。
#!/usr/bin/perl ############################################# # ディレクトリ作成のサンプル1 # Author: "Perl Programming Tips" ############################################# use File::Path; @pathArray = ('dir1/subdir1/subdir2', 'dir2/subdir1'); # ディレクトリの作成 mkpath(@pathArray, {verbose => 1});
実行結果は次のようになります。
[g@710m temp]$ tree . |-- file12_01.pl `-- file12_02.pl 0 directories, 2 files [g@710m temp]$ perl file12_01.pl mkdir dir1 mkdir dir1/subdir1 mkdir dir1/subdir1/subdir2 mkdir dir2 mkdir dir2/subdir1 [g@710m temp]$ tree . |-- dir1 | `-- subdir1 | `-- subdir2 |-- dir2 | `-- subdir1 |-- file12_01.pl `-- file12_02.pl 5 directories, 2 files [g@710m temp]$
ディレクトリパスを作成するには、File::Path::mkpath関数を使います。この関数は指定したディレクトリパスをサブディレクトリまで含めて作成します。UNIXの「mkdir -p」のような動作をします。ディレクトリパスは絶対パスまたは相対パスで指定します。
mkpathの第一引数にはディレクトリパスをリストで指定できるので、複数のディレクトリパスを一度に作成できます。第二引数にはmkpathの動作に関するオプションをハッシュへのリファレンスで渡します。省略した場合はデフォルトの動作になります。
mkpath関数に指定できるオプションには次のようなものがあります。
次は、ディレクトリツリー削除の簡単なサンプルです。
#!/usr/bin/perl ############################################# # ディレクトリ削除のサンプル1 # Author: "Perl Programming Tips" ############################################# use File::Path; @pathArray = ('dir1', 'dir2'); # ディレクトリの削除 rmtree(@pathArray, {verbose => 1});
実行結果は次のようになります。
[g@710m temp]$ tree . |-- dir1 | `-- subdir1 | `-- subdir2 |-- dir2 | `-- subdir1 |-- file12_01.pl `-- file12_02.pl 5 directories, 2 files [g@710m temp]$ perl file12_02.pl rmdir subdir2 rmdir subdir1 rmdir dir1 rmdir subdir1 rmdir dir2 [g@710m temp]$ tree . |-- file12_01.pl `-- file12_02.pl 0 directories, 2 files [g@710m temp]$
ディレクトリツリーを削除するには、File::Path::rmtree関数を使います。この関数は指定したディレクトリ以下のファイルやサブディレクトリを一括で削除します。UNIXの「rm -rf」のような動作をします。
rmtreeの第一引数にはディレクトリをリストで指定できるので、複数のディレクトリツリーを一度に削除できます。第二引数にはrmtreeの動作に関するオプションをハッシュへのリファレンスで渡します。省略した場合はデフォルトの動作になります。
rmtree関数に指定できるオプションには次のようなものがあります。
次に、mkpath、rmtree関数のエラー処理について補足しておきます。デフォルトではmkpath、rmtreeともに、エラーが発生した場合はCarp::carpを通してSTDERRにメッセージを出力します。致命的エラーが発生した場合はCarp::croakを通してプログラムを終了します。
この動作を変更したい場合は、errorオプションを使います。以下にerrorオプションを使ったエラーハンドリングのサンプルを示します。
#!/usr/bin/perl ############################################# # ディレクトリ削除のサンプル2 # Author: "Perl Programming Tips" ############################################# use File::Path; @pathArray = ('dir1', 'dir2'); # ディレクトリの削除 $ret = rmtree(@pathArray, {error => \$ref_err}); foreach (@$ref_err) { ($file, $message) = each(%$_); print "file:" . $file . " message:" . $message . "\n"; }
実行結果は次のようになります。
[g@710m temp]$ ll 合計 12 drwxrwxr-x 2 g g 4096 2008-07-29 05:58 dir1 drwxrwxr-x 2 g g 4096 2008-07-29 05:58 dir2 -rw-r--r-- 1 g g 413 2008-07-29 05:56 file12_03.pl [g@710m temp]$ ll -d ../temp/ dr-xr-xr-x 4 g g 4096 2008-07-29 05:59 ../temp/ [g@710m temp]$ perl file12_03.pl file:dir1 message:cannot remove directory: 許可がありません file:dir2 message:cannot remove directory: 許可がありません [g@710m temp]$
この例では、あらかじめディレクトリ「dir1」「dir2」を作成した後、親ディレクトリの書き込み権限をとってあります。こうするとディレクトリが削除できなくなります。この状態でrmtree関数を実行してみたのが上の実行結果です。
rmtree関数のオプションで「error」にリファレンス変数を渡します。このリファレンスはrmtreeの内部でリストへのリファレンスになります。このリストには、エラーが発生したファイル名をキー、その時のエラーメッセージを値としたハッシュへのリファレンスが格納されます。これをたどっていくと、エラーが発生したファイルとメッセージの一覧を取得することができます。