技術メモ

神奈川在住のITエンジニアの備忘録。おもにプログラミングやネットワーク技術について、学んだことを自分の中で整理するためにゆるゆると書いています。ちゃんと検証できていない部分もあるのでご参考程度となりますが、誰かのお役に立てれば幸いです。

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

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