ぽちは何かちょっとした作業なら大抵は Perl のワンライナーで済ませてしまいますけども、何度も何度も繰り返し使うものは、ちゃんとした Perlコードの実行ファイルにして取っておいたりします。ここにはそんな、ぽちにとって(だけ?)便利な小さな小さなツールたちをメモして置きます。
今ぽちが使っているいさましいちびのツールたちはこんな感じです。
debian squeeze で debパッケージでインストールする場合、libencode-locale-perl は squeeze-backports にしか無いので /etc/apt/sources.list に、
deb http://backports.debian.org/debian-backports squeeze-backports main
の一行を追記し、apt-get update してから apt-get install します。
$ sudo apt-get update $ sudo apt-get install libarchive-zip-perl libencode-locale-perl libpath-class-perl
場合によっては Mac の utf-8-mac で書かれたファイル名も扱えるように、Encode::UTF8Mac を debパッケージ化した libencode-utf8mac-perl_0.03-0+0pochi1_all.deb も用意してみました。
必要なら、
$ sudo dpkg -i libencode-utf8mac-perl_0.03-0+0pochi1_all.deb
とインストールすると簡単です。apt できちんとパッケージ管理をしたければ、apt-ftparchive を使って debパッケージの aptリポジトリを作るを参考にしてローカルな aptリポジトリを作ってみては如何でしょう?
#!/usr/bin/env perl
use strict;
use warnings;
use Archive::Zip qw/ :ERROR_CODES /;
use utf8;
use Encode;
# Mac の日本語ファイル名を扱う場合は Encode::UTF8Mac が必要です。
# utf-8-mac は自動推測の対象ではありません。
# utf-8-mac を扱う場合には必ず fオプションで指定して下さい。
#use Encode::UTF8Mac;
use Encode::Guess qw/ euc-jp cp932 iso-2022-jp utf8 /; # 自動推測の対象。
use Encode::Locale;
use Path::Class;
use Getopt::Std;
my %opts;
getopts('f:', \%opts);
@ARGV or die "Usage: unzip.pl [-f encoding_name] zip_file\n";
foreach ( @ARGV ) {
my $file = file $_;
my $zip = Archive::Zip->new();
$zip->read( "$file" ) == AZ_OK or die "Couldn't read: $file";
my $str;
$str .= $_->fileName foreach ( $zip->members );
my $enc;
if ( $opts{ f } ) {
$enc = $opts{ f };
} else {
my $enc_obj = Encode::Guess->guess( $str );
ref $enc_obj ? $enc = $enc_obj->name : die "Couldn't guess: $enc_obj";
}
foreach ( $zip->members ) {
my $file = file( encode( 'locale_fs', decode( $enc, $_->fileName ) ) );
my $dir = $file->parent;
-d $dir or dir( $dir )->mkpath;
print "extract $file ...";
$zip->extractMember( $_->fileName, "$file" );
print "done.\n";
}
}
exit;
この unzip.pl は、狐の王国の Suganoさんが以前公開されていた unzip.pl をもとに、ぽちにとって使い易いようにちまちまと改造を加えたものです。zipファイルの展開に一般に良く使われる unzip がマルチバイト文字のファイル名の展開に対応していないので、日本語名のファイルが入ってる迷惑な zipファイルを展開する時にはこれを使っています。個人的には環境に依存しないようにファイル名に使う文字は ASCII の範囲内に収めるようにしていますけども、他の方からいただくファイルはなかなかそうもいきません。
こんなふうに使います。
$ ./unzip.pl [-f エンコード名] zipファイル
基本的に fオプションは必要なく、unzip.pl は zipファイルの中のファイル名からエンコードされている文字コードを推測して、そのファイル名をローカル環境のファイルシステムでのロケールに合わせて変換し、展開します。たまに推測に失敗する時もありますが、そんな時はエラーメッセージを見て fオプションで適切な文字コードを指定してあげます。
debian squeeze への導入は enc.pl を参考にして下さい。Windows でインターネットへの接続環境があれば、ActivePerl なら ppm を使うとパッケージ化された必要な Perlモジュールをインストール出来ます。Strawberry Perl なら cpanm を導入して cpanm を使って CPAN から必要な Perlモジュールをインストールするのが良いでしょう。ぽちは Windows で使うのなら Strawberry Perl をお勧めします。
Windows での cpanm の導入から必要な Perlモジュールのインストールは、http://cpanmin.us を cpanm.pl という名前で適当な場所に保存し、管理者権限のあるアカウントでコマンドプロンプトから、
C:¥> perl cpanm.pl --self-upgrade C:¥> del cpanm.pl C:¥> cpanm Path::Class Encode::Locale Encode::UTF8Mac
で完了します。cpanm を使う時には、一緒に cpan-outdated や pm-uninstall をインストールすると Perlモジュールの管理になにかと便利です。
C:¥> cpanm App::cpanoutdated App::pmuninstall
#!/usr/bin/env perl
use strict;
use warnings;
use Archive::Tar;
use utf8;
use Encode;
# Mac の日本語ファイル名を扱う場合は Encode::UTF8Mac が必要です。
# utf-8-mac は自動推測の対象ではありません。
# utf-8-mac を扱う場合には必ず fオプションで指定して下さい。
#use Encode::UTF8Mac;
use Encode::Guess qw/ euc-jp cp932 iso-2022-jp utf8 /; # 自動推測の対象。
use Encode::Locale;
use Path::Class;
use Getopt::Std;
my %opts;
getopts('f:', \%opts);
@ARGV or die "Usage: untar.pl [-f encoding_name] tar_file\n";
foreach ( @ARGV ) {
my $file = file $_;
my $tar = Archive::Tar->new();
$tar->read( "$file" ) or die "Couldn't read: $file";
my $str;
$str .= $_ foreach ( $tar->list_files );
my $enc;
if ( $opts{ f } ) {
$enc = $opts{ f };
} else {
my $enc_obj = Encode::Guess->guess( $str );
ref $enc_obj ? $enc = $enc_obj->name : die "Couldn't guess: $enc_obj";
}
foreach ( $tar->list_files ) {
my $file = file( encode( 'locale_fs', decode( $enc, $_ ) ) );
my $dir = $file->parent;
-d $dir or dir( $dir )->mkpath;
print "extract $file ...";
$tar->extract_file( $_, "$file" );
print "done.\n";
}
}
exit;
この untar.pl は、Windows向け Perl の Strawberry Perl 5.12.3.0 と Perlモジュール以外にインストールを許されなかった父の Windows Vista機で、tar.gzファイルや tar.bz2ファイルを展開する為に unzip.pl を流用して作り直したものです。
最初は、
C:¥> perl -MArchive::Extract -e "$ae = Archive::Extract->new(archive => q/Path-Class-0.24.tar.gz/); $ae->extract;"
みたいにワンライナーで展開していたのですけれども、ついでなので unzip.pl みたいに、異なる日本語文字コードで書かれたファイル名を自動的にローカル環境の日本語文字コードに変換して展開してしまう untar.pl をでっちあげてみました。経験上 tar でアーカイブして gz や bz2 に圧縮するような方は、文字コードの環境に依存するような日本語名をファイルに付けたりしないので、あまり意味の無いツールかもしれません。
C:¥> perl untar.pl [-f エンコード名] tar.gzファイル または tar.bz2ファイル
見ての通り対象となるファイルのアーカイブ・圧縮形式が違うだけで、使い方は unzip.pl と同じです。
Windows への導入は untar.pl を参考にして下さい。debian squeeze で debパッケージでインストールする場合、libencode-locale-perl は squeeze-backports にしか無いので /etc/apt/sources.list に、
deb http://backports.debian.org/debian-backports squeeze-backports main
の一行を追記し、apt-get update してから apt-get install します。
$ sudo apt-get update $ sudo apt-get install libencode-locale-perl libpath-class-perl
場合によっては Mac の utf-8-mac で書かれたファイル名も扱えるように、Encode::UTF8Mac を debパッケージ化した libencode-utf8mac-perl_0.03-0+0pochi1_all.deb も用意してみました。
必要なら、
$ sudo dpkg -i libencode-utf8mac-perl_0.03-0+0pochi1_all.deb
とインストールすると簡単です。apt できちんとパッケージ管理をしたければ、apt-ftparchive を使って debパッケージの aptリポジトリを作るを参考にしてローカルな aptリポジトリを作ってみては如何でしょう?
#!/usr/bin/env perl
use strict;
use warnings;
use utf8;
use Encode;
# Mac の日本語ファイル名を扱う場合は Encode::UTF8Mac が必要です。
# utf-8-mac は自動推測の対象ではありません。
# utf-8-mac を扱う場合には必ず fオプションで指定して下さい。
#use Encode::UTF8Mac;
use Encode::Guess qw/ euc-jp cp932 iso-2022-jp utf8 /; # 自動推測の対象。
use Encode::Locale;
use Path::Class;
use Getopt::Std;
my %opts;
getopts('f:t:', \%opts);
@ARGV or die "Usage: enc.pl [-f encoding_name] [-t encoding_name] text_file\n";
foreach ( @ARGV ) {
my $file = file $_;
my $reader = $file->openr or die "Couldn't open $file for reading: $!";
my $content = $file->slurp;
$reader->close;
rename $file, "$file.bak";
my ( $from, $to );
if ( $opts{ f } ) {
$from = $opts{ f };
} else {
my $f_obj = Encode::Guess->guess( $content );
ref $f_obj ? $from = $f_obj->name : die "Couldn't guess: $f_obj";
}
if ( $opts{ t } ) {
$to = $opts{ t };
} else { $to = 'locale_fs'; }
$content = encode( $to, decode( $from, $content ) );
$from =~ /cp932|iso-2022-jp/ and $content =~ s/\r\n/\n/g;
$to =~ /cp932|iso-2022-jp/ and $content =~ s/\n/\r\n/g;
my $writer = $file->openw or die "Couldn't open $file for writing: $!";
$writer->print( $content );
$writer->close;
}
exit;
Windows向け Perl の Strawberry Perl 5.12.3.0 と Perlモジュール以外のインストールを認めてくれなかった父の Windows Vista機には、高機能なテキストエディタが入っていないので否が応にも CP932 と UTF-8 しか読めないメモ帳を使うしかありません。とは言うものの、最近少なくなったとはいえ EUC-JP や ISO-2022-JP のテキストファイルを読まざるを得ない場合もあったりします。この enc.pl は、unzip.pl や untar.pl の自動推測をもとに変換する部分を流用して、テキストファイルの中身を勝手にローカル環境の日本語文字コードに(ついでに改行コードも)変換するようにしたものです。
$ ./enc.pl [-f エンコード名] [-t エンコード名] テキストファイル
C:¥> perl enc.pl [-f エンコード名] [-t エンコード名] テキストファイル
基本的には fオプションや tオプションが無くても適切に変換します。変換前の文字コードの推測に失敗してエラーが出た時には fオプションで、変換後の文字コードをローカル環境のファイルシステムのロケールにしたくない場合には tオプションで、文字コードを指定して下さい。CP932 と ISO-2022-JP に変換する時にだけ改行コードが CRLF になります。また、変換前のファイルはファイル名の末尾に .bak を付けてバックアップとして取っておかれます。
動作確認環境 : Perl 5.10.1 on Debian GNU/Linux 6.0 squeeze, Strawberry Perl 5.12.3.0 on Windows Vista