なんと!unzipしたファイル名がSJISだった!コマンド?


SJISふぁっく

Linuxを使っていると国内からダウンロードしてきたzipファイルを展開した時に日本語ファイル名が化けてゲンナリ……って事がよくあります。で、いつもは気にせずそのまま使って、いらなくなったら破棄みたいな感じで。必要なファイルがある場合もたいした数じゃないので自分でリネームしてたんですが。今回、結構な数のファイルを直さないと使い物にならない状況があったので、ちょっと調べてみました。

原因

根本的にはWindows上でマルチバイトで動いてるアプリがcp932でファイル名を生でzipに埋め込んでるのが原因なんだけど。これがLinux側で展開される時にcp932のままファイルシステムに書き出されているのなら変換は楽。iconv -f shift-jis -t utf-8を通したリネームをシェルで回せば済む話。生で書き出す時にファイル名的にアウトなのは0x2Fだけなんだけど、これはcp932の2バイト目に含まれることはないので問題になる事はなさそう。なんだけど、非ASCII部分になんらかの変換がかかってしまっているらしく、うまく元に戻らない。

諦めてPythonで展開

検索したらStack OverflowでPythonで書けばえーやん、みたいなやりとりがあったので書いてみたら簡単だった。普段はグルー言語で便利ツール書くとかマメにできない人なんですよね。

unzip.py
#!/usr/bin/env python

import sys
import zipfile

def main(filename):
    with zipfile.ZipFile(filename) as zip:
        for info in zip.infolist():
            info.filename = info.filename.decode('shift-jis').encode('utf-8')
            zip.extract(info)

if __name__ == '__main__':
    sys.exit(main(sys.argv[1]))

エラー処理も何も考えてない単純に第一引数のzipファイルがSJISのファイル名を持ってると思ってただ展開するだけのスクリプト。

実はもっと簡単だった

で、Qiitaにでもメモっとくかー、と思って文字化け原因を掘り下げていったら灯台下暗し的な。きちんと文字コード変換するオプションが用意されてたorz

$ unzip -O sjis foo.zip

これだけで良いようでございます。なんか-Oと-Iが直感とは逆向きなんですが、-Oでアーカイブ内のエンコーディング、-Iで書き出し先のファイルシステムのエンコーディングを指定するようです。また変なエンコードがされてたのは自動判別に失敗してるためと思われます。

ソース見る前にhelpくらい読め、俺。さらに言えばQiitaにも答え書いてあるし。

まとめ

重い腰を上げて普段やらない事をやったら完全に無駄な作業でした。しかし、大きいコード書くのは好きなのに短いコード書くのが嫌いなのはなんでだろ。ボイラープレート比が高いからかなー。