2010年09月06日 23:00 [Edit]

perl - でWindows用のzipファイルをUnixで作る

何度目の車輪の再発明かわからないけど、見つからなかったものは見つからなかったので。


ezip.pl

新規に作成する場合は、こちら。

#!/usr/bin/env perl
#
# $Id: ezip.pl,v 0.1 2010/09/06 13:52:00 dankogai Exp dankogai $
#
use strict;
use warnings;
use Archive::Zip qw/:ERROR_CODES/;
use Getopt::Std;
use Encode;
use Unicode::Normalize;    # to handle UTF-8-MAC

my %opt = ( e => 'UTF-8' );
getopts( "e:" => \%opt );
my $encode = do {
    my $enc = find_encoding( $opt{e} ) or die "unknown encoding: $opt{e}";
    sub { $enc->encode( Unicode::Normalize::NFC( decode_utf8(shift) ) ) };
};

my $zipfile = shift; 
die "$0 -e encoding archive.zip path ..." unless @ARGV;
my $zip = Archive::Zip->new;
$zip->addTree($_, $_) for @ARGV;
my $error;
for my $m ( $zip->members() ) {
    $m->fileName( $encode->( $m->fileName ) );
}
$error = $zip->writeToFileNamed($zipfile) and die "$zipfile : error $error";

SYNOPSIS

% ezip.pl -e cp932 4win.zip 日本語の入ったpath …

convzip.pl

既存のzipアーカイヴをwindows用に仕立て直すときには、こちら。

#!/usr/bin/env perl
#
# $Id: convzip.pl,v 0.1 2010/09/06 13:52:00 dankogai Exp dankogai $
#
use strict;
use warnings;
use Archive::Zip qw/:ERROR_CODES/;
use Getopt::Std;
use Encode;
use Unicode::Normalize;    # to handle UTF-8-MAC

my %opt = ( e => 'UTF-8' );
getopts( "e:" => \%opt );
my $encode = do {
    my $enc = find_encoding( $opt{e} ) or die "unknown encoding: $opt{e}";
    sub { $enc->encode( Unicode::Normalize::NFC( decode_utf8(shift) ) ) };
};

my ( $srcfile, $dstfile ) = @ARGV;
die "$0 -e encoding from.zip to.zip" unless $dstfile;
my $zip = Archive::Zip->new;
my $error;
$error = $zip->read($srcfile) and die "$srcfile : error $error";
for my $m ( $zip->members() ) {
    $m->fileName( $encode->( $m->fileName ) );
}
$error = $zip->writeToFileNamed($dstfile) and die "$dstfile : error $error";

SYNOPSIS

% convzip.pl -e cp932 日本語の入った.zip 4win.zip

特長その他

  • Win側でファイル名を直すスクリプトは検索で見つかりますし、convmvの存在も知っていたのですが、圧縮する側で対処するスクリプトが見当たらなかったのでこさえました。
  • Mac以外でもたいていのUnix環境なら動きます。とりあえずFreeBSDとUbuntuでは確認済み
  • Archive::Zip::Memberのドキュメントがなくてちょっと苦労しましたが、$m->fileName()に引数を入れるとそれでrenameできることをソースを読んで知りました。

Enjoy!

Dan the Man with Too Many Encodings to Handle


この記事へのトラックバックURL