指定されたディレクトリ配下にあるアーカイブファイルを再帰的に展開するperlスクリプト extractRecursively.pl を作成した。
使い方は簡単で、「perl extractRecursively.pl "ディレクトリ"」として実行するだけ。
use strict; use warnings; use Archive::Zip; use File::Basename; use Getopt::Long; my $DEF_OF_ARC = '(\.zip$)|(\.jar$)|(\.war$)|(\.ear$)|(\.sar$)'; my $deleteArchiveFile; GetOptions( 'deleteArchiveFile' => \$deleteArchiveFile, ); my $dir = $ARGV[0]; if(! -d $dir){ die "Invalid argument."; } extract($dir); sub extract{ my $dir = shift; opendir(my $dh, $dir); my @fileList = readdir($dh); closedir($dh); foreach my $file (sort @fileList){ if($file =~ /^\.{1,2}$/){ next; } if(($file =~ /$DEF_OF_ARC/) && (-f "$dir/$file")){ extractZip("$dir/$file"); if(defined($deleteArchiveFile)){ unlink("$dir/$file"); } } if(-d "$dir/$file"){ extract("$dir/$file"); } } } sub extractZip{ my $zip = shift; my $dir = dirname($zip); my $archive = Archive::Zip->new($zip); my @members = $archive->memberNames(); foreach my $member (@members) { $archive->extractMember($member, "$dir/$member"); if(($member =~ /$DEF_OF_ARC/) && (-f "$dir/$member")){ extractZip("$dir/$member"); if(defined($deleteArchiveFile)){ unlink("$dir/$member"); } } if(-d $member){ extract("$dir/$member"); } } }
アーカイブファイルの種類は、ソースの最初の方の、
my $DEF_OF_ARC = '(\.zip$)|(\.jar$)|(\.war$)|(\.ear$)|(\.sar$)';
で指定できるので、必要に応じてここを編集する。
また、実行時に -d オプションを付けて、「perl extractRecursively.pl "ディレクトリ" -d」として実行すると、展開元のアーカイブファイルを展開後に消すことができる。
ソースの作りとしては、extract()とextractZip()が再帰的に自分を呼びつつ、お互いを呼び合うかたちになっている。もっとシンプルに書けそうな気もするが、とりあえず今はこれで使う。