← すべての記事

ZIP 文字化け Mac:Windowsで濁点が分かれる原因と直し方

Macで作ったZIPファイルをWindowsで開くと、ファイル名が読めなくなったり、「が」が「か゛」のように濁点だけ離れて見えたりすることがあります。原因は大きく2つあり、どちらもZIPの中身には触らずに直せます。1つはZIPに入っている文字コードの読み違い、もう1つはmacOS特有の分解された文字(NFD)です。この記事では、どちらの問題かを見分けてから直す方法を順番に説明します。

zip 文字化けが起きる原因

ZIPファイルは、ファイル名を「バイト列」と「そのバイト列がUTF-8かどうかを示す小さなフラグ」の組み合わせで保存しています。ファイルの中身は影響を受けないので、ファイル名さえ正しく読めれば書類は普通に開けます。壊れるのは名前の表示だけです。

よくある流れは次のとおりです。Macの同僚がFinderでフォルダを選び、「圧縮」を実行して、できた.zipをメールやチャットで送ってきます。受け取ったWindowsでエクスプローラーから「すべて展開」を選ぶと、フォルダの中に次のような名前が出てきます。

  • か゛いよう.pptx(本来はがいよう.pptx)
  • ハ゜リ見積.xlsx(本来はパリ見積.xlsx)
  • か゛ぞく写真.jpg(本来はがぞく写真.jpg)

別のパターンでは、縺ゅ・縺・.docxのように意味のない文字の並びになることもあります。これは本来UTF-8で書かれた名前を、Windowsが別の文字コードとして読んでしまった状態です。

見た目が似ていても、原因は2つに分かれます。

文字コードの読み違い(文字化け):アーカイバーがUTF-8のバイト列を書き出したのに、UTF-8であることを示すフラグが付いていなかったため、Windowsの標準展開機能が古い文字コードで読んでしまうケースです。名前そのものは壊れていません。読み方が間違っているだけです。

分解された文字(NFD):macOSは、濁点や半濁点、アクセント記号を、本体の文字とは別の文字として保存することがあります。「が」は「か」+「゛」、「é」は「e」+結合アクセントといった形です。Unicodeとしては正しく、Windowsでも開けますが、Windowsの多くのソフトやWebフォーム、サーバーは「合成済み」の形(NFC)を前提にしています。そのため、表示が割れて見えたり、エクスプローラーの検索に引っかからなかったり、アップロード画面で別のファイルとして扱われたりします。

手順1:どちらの問題かを確認する

展開したフォルダ(またはZIPをエクスプローラーで開いたまま)で、壊れた名前を1つ見てください。

  1. 名前に、どの単語にも見えない記号(例:縺、繧、é)が混ざっていれば、文字コードの読み違いです。「対処B」に進んでください。
  2. 名前は読めるのに、濁点や文字の一部が離れて見える場合は、NFDの可能性が高いです。次の方法で確認できます。
    • ファイルを右クリックして「名前の変更」を選びます。
    • Endキーを押してから、Backspaceを1回押します。
    • 濁点(または結合アクセント)だけが消えて、本体の文字が残れば、名前は分解されています。通常のNFCの名前では、Backspaceで「が」や「é」全体が消えます。

PowerShellが使える場合は、次のコマンドでも判定できます。

Get-ChildItem -Recurse -File | Where-Object {
  -not $_.Name.IsNormalized([Text.NormalizationForm]::FormC)
} | Select-Object FullName

一覧に出たファイルがNFDです。

対処A:濁点の分離(NFD)を直す

方法は2つあります。1つはブラウザだけで、ZIPをZIPのまま直す方法です。もう1つは、展開後のファイル名を直す方法です。

方法1:ブラウザでZIP内のファイル名を修復する

ZIPを別の人に送り直したい場合や、アーカイブの形を保ちたい場合に向いています。

  1. ブラウザでZIPファイル名修復ツールを開きます。
  2. ダウンロードフォルダなどから.zipファイルをページにドラッグ&ドロップします。200MBまでのアーカイブに対応しています。
  3. ツールがZIP内のファイル名をNFDからNFCに変換し、修正済みのZIPをダウンロードできるようにします。
  4. 新しいZIPを、いつもどおり「すべて展開」で開きます。がいよう.pptxなどが正しく表示され、エクスプローラーの検索にも出てくるようになります。

変換はブラウザ内で行われ、ファイルやファイル名がサーバーにアップロードされることはありません。取引先の契約書や人事関係の書類が入ったZIPを扱う場合も、この点は確認しやすいと思います。料金はかかりません。すでに展開してバラバラのファイルになっている場合は、同じサイトでファイルをドラッグ&ドロップして、まとめて名前を変更できます。

方法2:展開後にPowerShellで一括変換する

Windowsには標準で.NETが入っており、Unicodeの正規化に対応しています。元のフォルダを壊したくない場合は、先にフォルダをコピーしてから作業してください。このコマンドは名前をその場で書き換えます。

  1. ZIPを通常どおり展開します。
  2. 展開先のフォルダを開き、アドレスバーをクリックしてpowershellと入力し、Enterを押します。そのフォルダでPowerShellが開きます。
  3. 次のコードを貼り付けてEnterを押します。
Get-ChildItem -Recurse -File | ForEach-Object {
  $nfc = $_.Name.Normalize([Text.NormalizationForm]::FormC)
  if ($nfc -ne $_.Name) {
    Rename-Item -LiteralPath $_.FullName -NewName $nfc
  }
}
  1. フォルダ名も壊れている場合は、-Fileを-Directoryに変えて、もう一度実行します。フォルダ名を先に変えると、中のファイルのパスが変わってしまうので、ファイルを先に処理してください。

単発の作業や、ビルドスクリプトに組み込みたい開発者にはこの方法が向いています。ただし、元のZIPは変わりません。また、別のフォルダで実行してしまうと取り返しがつかないので、実行前にカレントディレクトリを確認してください。

対処B:文字コードの読み違いを直す

「縺」や「繧」のような文字化けが出ている場合は、名前の正規化では直りません。まず、名前をUTF-8として正しく読む必要があります。

  1. 無料のアーカイバー「7-Zip」(7-zip.org)などをインストールします。UTF-8フラグが欠けていても、名前を正しく読めることが多いです。Windowsの標準展開機能で文字が崩れる場合に、役立つことがあります。
  2. ZIPを右クリックして、7-Zip → ここに展開(または"フォルダ名" に展開)を選びます。
  3. 名前が読めるようになっていれば、ここで完了です。
  4. 名前は読めるのに濁点が離れている場合は、2つの問題が同時に起きていたことになります。「対処A」に戻り、展開したファイルを正規化してください。

それでもサードパーティ製のツールで意味のない名前になる場合は、送り手のアーカイバーがUTF-8ではなく古い文字コードで書き出している可能性があります。その場合は、送り手にZIPを作り直してもらうのが一番早いです。Macの標準の「圧縮」や一般的なアプリは通常UTF-8で書き出します。問題が起きやすいのは、古いツールや特殊なツールを使っている場合、または言語設定の違うWindowsパソコンでZIPを作り直した場合です。

次から避けるための習慣

送る側と受け取る側で、少し気をつけるだけでこの問題のほとんどは防げます。

Macから送る側の場合:圧縮する前に、フォルダ内の名前をNFCに変換しておくと安心です。または、ZIPを送る代わりにクラウドストレージの共有リンクを使う方法もあります。ただし、クラウドによっては、アップロード時に名前を正規化しないこともあるので、テスト用のファイルで一度確認してください。Webフォームに直接ファイルをアップロードする場合は、FilenameFixer Chrome拡張機能が、Webサイトへのアップロード時にファイル名を自動で修正します。受け取る側のシステムにすでに登録されている名前と一致しないことでフォームが弾く、といった事態を減らせます。

Windowsで受け取る側の場合:7-Zipなどの展開ツールを入れておき、Macで作られたZIPから日本語や濁点つきの名前が出てきたら、手で名前を直す前に、10秒のBackspaceテストを試してください。多くのフォントでは、分解された名前と合成された名前が同じに見えます。そのため、手作業で名前を直すと、同じ名前に見えるファイルが2つ残ってしまうことがあります。

開発者の場合:ファイルのアップロード処理、同期スクリプト、ビルド処理など、アプリケーションの入口でNFCに正規化しておくのが確実です。Pythonではunicodedata.normalize("NFC", name)、Node.jsではname.normalize("NFC")、.NETではString.Normalize()が使えます。macOSではテストが通るのに、Linuxの継続的インテグレーション環境で失敗する、というときの原因として、「同じに見えるファイル名がバイト列として違っている」ケースはよくあります。

どちらの対処でも、書類の中身が変わることはありません。最悪の場合でも、ZIPをもう一度展開し直すだけで済みます。