22 February 2011

(Ubuntu 10.04) 書庫マネージャ(File Roller)で日本語エラー

Ubuntu 10.04 の書庫マネージャで日本語のファイル名を持つファイルを格納しているzipファイルを開くと、日本語がエラーとなり解凍も閲覧も出来ない

20110222-fileroller-error.jpg
日本語部分がエラーになった状況

Google検索で原因を探ってみると
・unzip コマンドが日本語を通さない場合
・7zipがインストールされている場合
の2種類があると分かった。

Ununtu 10.04 日本語Remixバージョンは日本語を通すunzipがインストールされているはずだが、とりあえずコマンドラインで確認


$ unzip -l 確定申告.zip

Archive: 確定申告.zip
Length Date Time Name
-------- ---- ---- ----
0 02-21-11 22:29 確定申告書/
15459 07-11-10 08:54 確定申告書/添付台紙.pdf
20746 10-26-10 07:35 確定申告書/第一表.pdf
20746 10-26-10 07:35 確定申告書/第二表.pdf
22887 06-04-02 23:39 特定口座 年間取引報告書.pdf
-------- -------
79838 5 files

確かに、10.04LTSでは日本語を通すようだ。

ということで、p7zip-full をapt-getでアンインストールする。(依存関係にあるacentoneiso とunetbootin が同時にアンインストールされる)

そして、再び書庫マネージャでzipを開いてみると、ちゃんと日本語が認識されている。

20110222-fileroller-pass.jpg
7zipをアンインストールして、日本語が認識された状態

どうしても7zipをアンインストールしたくない場合は、次のようなPerlスクリプトで、無理やり日本語のファイル名のファイルを解凍できる可能性もある

日本語(シフトJIS)を含んだzipやlzhをUTF-8に変換しながら解凍する」に掲載されていたスクリプトに、「\」がパス名にある場合「/」に変換するという1行を加えた

unzip-ja.pl
#!/usr/bin/perl
# ファイル名をSJISからUTF-8に変換しながらzipを解凍する
 
use strict;
use warnings;
use Archive::Zip qw( :ERROR_CODES :CONSTANTS );
use File::Basename;
use Getopt::Long;
use DateTime;
use DateTime::TimeZone::Local;
use Encode;
 
use Data::HexDump;
 
my $flag_list = 0;        # リスト表示モードの時 1
 
GetOptions('list|l' => \ $flag_list);
if (scalar @ARGV < 1) {
    print("Usage: ".basename($0)." [-l] zipfile\n");
    exit(1);
}
my $zipfile = shift @ARGV;
 
my $zip = Archive::Zip->new();
unless ( $zip->read($zipfile) == AZ_OK ) {
    die("zip file read error\n");
}
print("Archive: $zipfile\n");
if ($flag_list == 1) {
    print <<HERE;
   Length     Date    Time   Name
 --------  ---------- -----  ----
HERE
}
my $total_size = 0;
my @members = $zip->members();
my $members_count = scalar @members;
foreach my $member (@members) {
    my $filename = $member->fileName;
    Encode::from_to($filename, 'shiftjis', 'utf8');
    $filename =~ s|\\|/|g;        # DOSのディレクトリ記号 \ を / に変換
    if ($flag_list == 1) { # リスト表示モード
    my $dt = DateTime->from_epoch(
        epoch => $member->lastModTime
    )->set_time_zone(DateTime::TimeZone::Local->TimeZone());
    $total_size += $member->uncompressedSize;
    printf "%9d  %s  %s\n",
        $member->uncompressedSize,
        $dt->ymd('-') . ' ' . sprintf("%02d", $dt->hour) . ':' . sprintf("%02d", $dt->min),
        $filename;
    } else { # 解凍モード
    print "  inflating: $filename\n";
    unless (defined $zip->extractMember($member, $filename)) {
        warn "  failed: $filename\n";
    }
    }
}
my $members_count_str = "$members_count file" . ($members_count > 1 ? 's' : '');
if ($flag_list == 1) {
    print <<HERE;
 --------                    -------
HERE
    printf "%9d                    %s\n", $total_size, $members_count_str;
}