Windowsで作ったzipファイルをMacで展開するとファイル名が文字化けする問題

日本の商習慣として未だに残っているのが「ファイルをまとめてzipで渡す」というやつである。数年前までビジネスで使われるコンピュータはWindowsデファクトスタンダードだったので、zipファイルを作成するのも、展開するのも同じソフトウェアを使っていたから特に問題が起きることはなかった。古き良き時代であるが、近年ではMacOSも普及し、ビジネスでファイルをやりとりするのに使えるようになってきた。複数のOSが併用されるようになったが、相変わらずファイルのやりとりはzipで行われるという商習慣の形として残った。

私の意見はそもそもそういう商習慣を撤廃するべきだということに尽きるのだが、家族を養う手前既存の商習慣に従わなければならない。そしてここ数年は、仕事でもMacOSを使っている。MacOSWindowsの間でファイルをやり取りするときの問題その1は暗号化zipである。問題その2は表題にあるとおり、日本語のファイル名を持つファイルが文字化けしてしまい、意味のあるファイル名だったときにビジネス上のコミュニケーションに支障が出てしまうことである。

もしビジネスでなかったらそんなファイルはすぐにrmしてしまうべきであるが、ここまで読んで頂いたということは、読者諸賢もこの問題でお困りのことであろうから、私の調べたことがいくらかでもお役に立てば幸いである。

TL;DR

なぜファイル名が文字化けするのか

Windowsファイルシステムでは、基本的に日本語のファイル名はcp932でエンコードされている。後方互換姓のためこれが今後も変わることはないと思われる。また、最新のWindowsでもUTF-8などでファイル名をエンコードしてzipアーカイブを作ることはできないようだ。Explororのメニューからアーカイブを作るとcp932でファイル名もzipアーカイブ内に保存されてしまう。7zipなどのサードパーティのアプリケーションを使えば、Unicodeアーカイブすることができる。

また、ZIPの仕様では、ファイル名のエンコーディングに関する指定はAppendix Dに 「歴史的にIBMコードページ437しかサポートしていなかった」と書かれている。CP437とは何かというと、いわゆるASCIIのセットにラテン文字を追加したもののようで、当然日本語の文字が入っているわけではない。CP437はDOSOEMコードセットというらしい。ここでいうDOSはMS DOSのことであるから、WindowsIBMコードページが追加されていき、日本語版Windowsファイルシステムの標準文字コードとして、また、そこから作られるZIPアーカイブでCP932が採用されることのは歴史的な経緯としては自然なようだ。

一方、MacOSのファイルシステムは、 APFS でも HFS+ では、基本的にUTF-8でファイル名がエンコードされている

APFS has case-sensitive and case-insensitive variants. The case-insensitive variant of APFS is normalization-preserving, but not normalization-sensitive. The case-sensitive variant of APFS is both normalization-preserving and normalization-sensitive. Filenames in APFS are encoded in UTF-8 and aren’t normalized.

HFS+, by comparison, is not normalization-preserving. Filenames in HFS+ are normalized according to Unicode 3.2 Normalization Form D, excluding substituting characters in the ranges U+2000–U+2FFF, U+F900–U+FAFF, and U+2F800–U+2FAFF.

Finderのメニューで展開しても、 `/usr/bin/unzip` を利用しても、基本的には zip アーカイブ内のファイル名のところにあるバイト列をそのままファイル名として展開する。したがって、UTF-8しか対応していないHFS+のファイル名に、CP932でエンコードされた文字列が保存されてしまう。Finderを始めとした各種アプリケーションはHFS+の仕様に従ってUTF-8だと思ってCP932のファイル名を表示するので、よくわからない化けたファイル名が表示されることになる。
 
まとめると、WindowsではCP932でZIPを作る、ZIPは慣習的にCP932やCPxxxでのファイル名のエンコードを許容している、MacOSはそんなことしらないでUTF-8として扱う、のコンボで、結果的にこういうことになるようだ。

f:id:kuenishi:20170508224724p:plain

ワークアラウンド、今後の期待

Macに含まれているInfo-ZIPが6.00であるから、それが最新版にアップデートされれば解決するか?という答えは半分正解で、半分不正解だ。まず、このCP932対応が含まれているバージョンがまだ正式にリリースされておらず、ベータ版が 2010年にリリースされて以来ずっと放置されている。どうもやる気がないないらしい。スレも立っているがやはり放置されているので期待できない。こんなに必要とされているソフトウェアなのにリリースされないとは、OSSはさすがにかくあるべしといった感がある。

もし万が一これがリリースされたとして、MacPortsに入るのは早いだろうが、MacOSのリリースにバンドルされるのはいつのことになるやら知れたものではない。現にPythonは2.7だし、Rubyだって今みたら未だに2.0.0である。

つまり公式は期待できないので、ZIPファイルを受け取るMacOS側がどうするべきかというと、

くらいが関の山である。

次点で期待できるものとして、Goで書かれた mholt/archiver にパッチを当てるというものがある。 x/text/encoding/japanese を使うとよさそう。有志に期待している。もしGoを書きたくなったら僕がやるかもしれない。

ZIPアーカイブを作る側、Windows側でできることがあるとすれば、 UTF-8 によるエンコードはサポートされていないようなので、もし相手がMacユーザーだと分かっている場合は、予め 7zip 等のサードパーティツールを使ってUTF-8でZIPアーカイブを作成するのがよさそうである。

おまけ、問題3、逆: Macで作ったzipアーカイブが中に日本語のファイル名を持つときにWindowsでファイル名を文字化けさせずに展開できるか

UTF-8のファイル名が保存されたものは Windows 7のあるバージョンからできるようになっている。これは、ZIPの仕様に、ファイル名がUTF-8エンコードされていることを示すフラグがあり、それに従ってファイル名を変換しているようだ。

   4.4.4 general purpose bit flag: (2 bytes)
   ...(snip)...
        Bit 11: Language encoding flag (EFS).  If this bit is set,
                the filename and comment fields for this file
                MUST be encoded using UTF-8. (see APPENDIX D)


しかしながら、 MacOS のFinderでのアーカイバはそのフラグをつけずに UTF-8エンコードしてしまうらしい。

一方MacOSに含まれている "/usr/bin/zip" コマンドは Info-ZIP の 3.0 なので問題はなさそうだ *1 。リリースノートに "Unicode (UTF-8) filename and (partial) comment support" と書かれている。

*1:Finderはこのツールを使っていないということか…?!