他のシステムで作成されたZIPファイルを解凍した際に日本語ファイル名が文字化けする不具合への対処法をいくつか。
Windows7 の場合
標準の状態だと、Shift-JIS(CP932)以外でエンコードされていると、文字化けする。
AmazonのMP3ストアを初めて利用したのだが、ダウンロードしたZIPファイルの中身が盛大に文字化けしている…UTF-8エンコード? pic.twitter.com/324ZFNphUK
— 風柳 (@furyutei) October 11, 2015
これまでは
などを使うことで対処していたが、日本語ファイル名が UTF-8 でエンコードされているものについては、Windows7・Windows Server 2008 R2 用 Hotfix を適用すれば解消される模様。
File names are corrupted after you decompress a .zip file in Windows 7 or in Windows Server 2008 R2
https://t.co/QOurlBDWb5
のHotfixを適用したら、文字化けが解消された(Windows7)。 pic.twitter.com/MWILrCKfZK
— 風柳 (@furyutei) October 11, 2015
CentOS 6 の場合(unzip)
CentOS 6 系で yum を使ってインストールできる unzip (CentOS 6.6では現在 unzip-6.0-2.el6_6.x86_64) では、日本語ファイル名には未対応のため、エンコードに関わりなく文字化けしてしまう。
【UTF-8 エンコード時】
$ /usr/bin/unzip -l ./AmazonMusicDownload.zip Archive: ./AmazonMusicDownload.zip Length Date Time Name --------- ---------- ----- ---- 8381815 10-11-2015 01:53 ?????????????(???????????????)/Cherish you/01 - Cherish you.mp3 9099388 10-11-2015 01:53 ?????????????+?????????????????/?????????????+????????????????? ??????????????+??+????????+???????????????/01 - Blooming Lily.mp3 8447415 10-11-2015 01:54 ?????????????+?????????????????/?????????????+????????????????? ??????????????+??+????????+???????????????/03 - ???????????????????????????.mp3 --------- ------- 25928618 3 files
【Shift-JIS エンコード時】
$ /usr/bin/unzip -l ./sjis-sample.zip Archive: ./sjis-sample.zip Length Date Time Name --------- ---------- ----- ---- 0 10-11-2015 10:59 ?????+???????????-????/?????+???????????-???? ?L?????N?^?[?C???[?W?\???O?W/ 9099388 10-11-2015 01:53 ?????+???????????-????/?????+???????????-???? ?L?????N?^?[?C???[?W?\???O?W/01 - Blooming Lily.mp3 8447415 10-11-2015 01:54 ?????+???????????-????/?????+???????????-???? ?L?????N?^?[?C???[?W?\???O?W/03 - ?`???X?L?????_???X.mp3 0 10-11-2015 10:59 ?X?????q??(???????F??)/Cherish you/ 8381815 10-11-2015 01:53 ?X?????q??(???????F??)/Cherish you/01 - Cherish you.mp3 --------- ------- 25928618 5 files
そこで、unzip 6.0 Shift-JIS対応版 をインストールすることで対応してみることに。
unzip 6.0 Shift-JIS対応版のインストール方法
$ git clone https://github.com/ted-n/unzip.git $ cd unzip/unzip60 $ make -f unix/Makefile LOCAL_UNZIP="-D_FILE_OFFSET_BITS=64 -DNO_LCHMOD -D_MBCS -DNO_WORKING_ISPRINT" generic_gcc $ sudo make -f unix/Makefile install
これで、/usr/local/bin 下にパッチの当たった unzip がインストールされる。
一行目を修正("git clone git@github.com:ted-n/unzip.git"としていたが、これは予めSSH Keyの設定が必要なため)
【UTF-8 エンコード時】
$ /usr/local/bin/unzip -l ./AmazonMusicDownload.zip Archive: ./AmazonMusicDownload.zip Length Date Time Name --------- ---------- ----- ---- 8381815 10-11-2015 01:53 氷堂美智留(矢作紗友里)/Cherish you/01 - Cherish you.mp3 9099388 10-11-2015 01:53 冴えない彼女の育てかた/冴えない彼女の育てかた キャラクターイメージソング集/01 - Blooming Lily.mp3 8447415 10-11-2015 01:54 冴えない彼女の育てかた/冴えない彼女の育てかた キャラクターイメージソング集/03 - 饒舌スキャンダラス.mp3 --------- ------- 25928618 3 files
【Shift-JIS エンコード時】
$ /usr/local/bin/unzip -l ./sjis-sample.zip Archive: ./sjis-sample.zip Length Date Time Name --------- ---------- ----- ---- 0 10-11-2015 10:59 冴えない彼女の育てかた/冴えない彼女の育てかた キャラクターイメージソング集/ 9099388 10-11-2015 01:53 冴えない彼女の育てかた/冴えない彼女の育てかた キャラクターイメージソング集/01 - Blooming Lily.mp3 8447415 10-11-2015 01:54 冴えない彼女の育てかた/冴えない彼女の育てかた キャラクターイメージソング集/03 - 饒舌スキャンダラス.mp3 0 10-11-2015 10:59 氷堂美智留(矢作紗友里)/Cherish you/ 8381815 10-11-2015 01:53 氷堂美智留(矢作紗友里)/Cherish you/01 - Cherish you.mp3 --------- ------- 25928618 5 files
Python で Shift-JIS エンコードしたファイル名で圧縮する場合の注意
自分はこれまで、Linux(CentOS) 上の Python で日本語ファイル名を含んだ ZIP ファイルを作成する場合でも、Windows で扱いやすくするために Shift-JIS(CP932) でエンコードしたファイル名で圧縮していたのだが、こうして作成したファイルを上記のパッチ済みの unzip で表示すると、なぜか文字化けしてしまった。
【オリジナルの unzip 6.0 使用時】
$ /usr/bin/unzip -l ./test.zip Archive: ./test.zip Length Date Time Name --------- ---------- ----- ---- 400 10-11-2015 15:57 ???{????f?B???N?g??/???{???t?@?C????.txt --------- ------- 400 1 file
【パッチ済みの unzip 使用時】
$ /usr/local/bin/unzip -l ./test.zip Archive: ./test.zip Length Date Time Name --------- ---------- ----- ---- 400 10-11-2015 15:57 傔 ・fB Ng /傔 黎@C シ.txt --------- ------- 400 1 file
調べてみると、どうも ZIP ファイルヘッダの version(ZipInfo.create_system) が 3 (Unix) になっているとこの現象が発生するようなので、これを考慮して Python スクリプトを作成する必要がある模様。
zipfile.py の class ZipInfo の定義を見てみると、sys.platform が 'win32' のときは self.create_system に 0 が、それ以外は 3 がデフォルトで設定されている。
【例】
import czipfile as zipfile import datetime zip = zipfile.ZipFile( 'test.zip', 'w' ) timestamp = datetime.datetime.now() dir_filename = u'日本語のディレクトリ/日本語ファイル名.txt' content = 'test' * 100 zipinfo = zipfile.ZipInfo( filename = dir_filename.encode( 'cp932', 'replace' ), date_time = ( timestamp.year, timestamp.month, timestamp.day, timestamp.hour, timestamp.minute, timestamp.second ) ) zipinfo.compress_type = zipfile.ZIP_DEFLATED zipinfo.create_system = 0 # 0 - MS-DOS and OS/2 (FAT / VFAT / FAT32 file systems), 3 - UNIX (https://pkware.cachefly.net/webdocs/casestudies/APPNOTE.TXT) zip.writestr( zipinfo, content ) zip.close()
$ /usr/local/bin/unzip -l ./test.zip Archive: ./test.zip Length Date Time Name --------- ---------- ----- ---- 400 10-11-2015 15:59 日本語のディレクトリ/日本語ファイル名.txt --------- ------- 400 1 file
追記(2015/10/26)
- Fedora(20以降だとyumでインストール可能)や CentOS 7(RPMが利用可能) だと、unar を使えばよい模様(おーのさんのコメントより)
- unzip 6.10b であれば、CP932 に対応している模様