Akira's Blog

神奈川在住のITエンジニアの雑記です。主にプログラミング(Perl, Java etc)やネットワーク技術について、ちょっとずつ書いていきます。

指定されたディレクトリ配下のアーカイブファイルを再帰的に展開するスクリプトを作成した。

指定されたディレクトリ配下にあるアーカイブファイルを再帰的に展開する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()が再帰的に自分を呼びつつ、お互いを呼び合うかたちになっている。もっとシンプルに書けそうな気もするが、とりあえず今はこれで使う。