任意のファイル名でZipファイルを解凍するスクリプト
以前にMacユーザとWindowsユーザがZipファイルをやり取りすると、Zipファイル内で保持されている日本語ファイル名の文字コードの問題で、解凍できないことがあると聞きました。本当なのかどうかと、いまだにそうなのか分からないのですが、ふと思い出したのでPerlとArchive::Zipモジュールを使って、解凍後のファイル名を指定できるunzipスクリプトを。
use Archive::Zip;
my %opts = ();
my $archive = undef;
while ($_ = shift(@ARGV)) {
if ($_ =~ /^-/) { $opts{$_} = @ARGV ? shift(@ARGV) : undef }
else { $archive = $_; }
}unless ($archive) {
print qq(Usage : perl unzip.pl "example.zip" -o "example/directory/basename"\n);
print qq(Note : File name will be "basename" + "_" + sequential number + original file extension);
exit;
}die qq("$archive" does not exists.) unless (-f $archive);
my $output = $opts{'-o'} ? $opts{'-o'} : './zipped';
my $zip = Archive::Zip->new();
die qq(Can't read "$archive".) unless $zip->read($archive) == AZ_OK;
print "Extracting " . $zip->numberOfMembers($archive) . " files from $archive\n";my @members = $zip->members();
@members = grep { $_->fileName !~ /[\\\/:]$/ } @members; # ディレクトリを除外
@members = sort { $a->fileName cmp $b->fileName } @members;
$output =~ s/%/%%/g;
$output = $output . '_%0' . length($#members + 1) . 'd';
for (my $i = 0; $i < @members; $i++) {
my $number = $i + 1;
my $member = $members[$i];
my $org = $member->fileName;
my $ext = ($org =~ /\.(\w+)$/) ? $1 : 'bin';
my $path = sprintf($output, $number) . ".$ext";
print "extract $org -> $path\n";
$zip->extractMember($member, "$path")
}
これを“unzip.pl”などのファイル名で保存し、次のような感じで使います。
perl unzip.pl "解凍するZipファイル名" -o "解凍ディレクトリ/ファイルのベース名"
解凍後のファイル名には、上で指定したベース名に、"_001"のような連番と、元のファイルの拡張子がつけられます。連番はZipファイル内のメンバー順ではなく、元のファイル名のアスキー順でふられます。
あとはPARでexe化してあげると良いのだろうけど、とりあえず割愛。
(2007/08/15追記)
「OpnePNEの最新日記をRSSに吐き出す:さむしんぐにゅぅ」のgenrss.zipをWindowsで展開できなくて、このスクリプトを試したらうまくいきました。リソースフォーク(って呼び方をOS Xでもするのでしょうか?)らしきファイルもでてきたけど。