Macのファイル名がWindowsで濁点が分離する原因と直し方|NFD・NFCの違い
Macで作ったファイルをWindowsに渡したら、「資料.pdf」の「が」が「か」と「゛」に分かれて表示された。検索しても見つからない、システムにアップロードするとエラーになる——そんな状況の記事です。
結論から言うと、原因は壊れたデータではなく、同じ文字が別の並べ方で保存されているだけです。ファイル名を「合成形式(NFC)」にそろえれば直ります。この記事では、症状の見分け方、Windowsでの一括変換、そして変換するときに起きやすい落とし穴を整理します。
結論:濁点の分離は「NFD」と「NFC」の違い
日本語の「が」は、Unicode上で2通りの表し方があります。
| 形式 | 呼び方 | 「が」の中身 |
|---|---|---|
| NFC(合成済み) | 1文字で表す | U+304C(が)の1文字 |
| NFD(分解) | 基底文字+濁点で表す | U+304B(か)+U+3099(結合用濁点)の2文字 |
画面では同じ「が」に見えても、コンピューターにとっては別の文字列です。Macの環境では、ファイル名がNFD(濁点が分解された形)で扱われる場面があり、それをWindowsに持っていくと「か゛」のように分かれて見えることがあります。
同じ見た目でも、NFDとNFCは別の文字列として比較されます。これがこの問題のすべての原因です。
なお、Mac側の保存の仕組み(どのファイルシステムでどう正規化されるか)は、OSやファイルシステムのバージョンによって異なるとされています。本記事は公式仕様の解説ではなく、症状の見分け方と対処に絞った実務メモです。Appleやマイクロソフトの公式情報が必要な場合は、各社の資料を確認してください。
影響を受ける文字
分解されるのは、主に濁点・半濁点が付く文字です。
- が行・ざ行・だ行・ば行(濁点)
- ぱ行(半濁点)
- カタカナの濁音・半濁音(ガ、パ、ヴなど)
- 欧文のアクセント付き文字(é など)
一方、漢字・ひらがなの清音・長音「ー」は、変換しても1文字のままです。つまり「資料」「報告書」のようなファイル名は症状が出ず、「がっこう」「パンフレット」のように濁点を含む名前だけがおかしくなるため、「たまに起きる不具合」に見えがちです。
症状から原因を切り分ける
「濁点が分離する」という症状と、「ファイル名が完全に文字化けする」症状は、別の問題です。最初に切り分けます。
| 見え方 | 考えられる原因 | 対処の方向 |
|---|---|---|
| 「か゛」と、濁点だけ浮いて見える | 正規化形式の違い(NFD) | NFCへ変換(本記事) |
| 意味の読めない文字や記号の羅列になる | 文字コードの解釈違い(ZIPなど) | 解凍ソフトや解凍時の文字コード指定を見直す |
| 検索しても見つからないが、見た目は同じ | NFDとNFCの不一致の可能性 | 次の手順で確認 |
ZIPで完全に化ける場合は、WSL2の unzip -Ocp932 で回避できたという報告もあります(個人の検証例で、環境によって結果は異なると考えられます)。PDFの添付ファイル名や本文が化ける場合は、PDFが文字化けする原因と直し方も確認してください。
見た目では判断できない:ツールで確認する方法
NFDかNFCかは、目視ではほぼ判断できません。フォントによっては、NFDの「が」が合成形と見分けがつかないほど綺麗に表示されます。次の3つの方法なら、ブラウザだけで確かめられます。
1. 文字数を数える
文字数カウントツールにファイル名を貼り付けます。このツールは文字数をコードポイント単位で数え、UTF-8のバイト数も表示します。
筆者が がぎぐパ資料ファイル.txt(見た目は14文字)をNFCとNFDで実測した結果は次のとおりです。
| 形式 | 文字数(コードポイント) | UTF-8バイト数 |
|---|---|---|
| NFC | 14 | 34 |
| NFD | 18 | 46 |
見た目が同じなのに、文字数が4文字、バイト数が12バイト多いなら、濁点が分解されています。濁点・半濁点の数だけ、文字数は1ずつ、バイト数は3ずつ増える計算です(上の例では濁点系が4文字)。
2. 差分を取る
テキスト差分比較ツールの左右に、「Macから来たファイル名」と「Windowsで打ち直したファイル名」を貼り付けます。見た目が同じでも、行が「変更あり」と判定されたら、中身が違います。このツールは行を完全一致で比較するため、NFDとNFCの違いも差として出ます。
3. URLエンコードして見る
URLエンコードツールに通すと、バイト列の違いがはっきり出ます。「が」で実測すると次のようになりました。
| 形式 | encodeURIComponent の結果 |
|---|---|
| NFC | %E3%81%8C |
| NFD | %E3%81%8B%E3%82%99 |
NFDの結果の後半 %E3%82%99 が結合用濁点(U+3099)です。ファイル名をURLに含めたとき、%E3%82%99 が混ざっていたらNFDの目印になります。URLまわりの文字化けは、URLエンコードで文字化けが直らない原因も参考になります。
Windowsでファイル名をNFCに直す方法
見た目や文字数で原因を確かめたら、ファイル名をNFCに変換します。
方法1:PowerShellで一括変換する
次のコマンドは、指定フォルダ直下のファイルのうち、NFCになっていないものだけを変換します。実際にWindows(PowerShell 5.1)で、NFDのファイル名を作って試した手順です。
# 対象フォルダを指定(例)
$dir = "C:\work\from-mac"
Get-ChildItem -LiteralPath $dir |
Where-Object { -not $_.Name.IsNormalized([Text.NormalizationForm]::FormC) } |
ForEach-Object {
Rename-Item -LiteralPath $_.FullName `
-NewName $_.Name.Normalize([Text.NormalizationForm]::FormC)
}
実測では、NFDの「資料がめ.txt」と「パ.txt」が、変換後にそれぞれ8文字・5文字のNFCの名前になりました。サブフォルダまで処理したい場合は Get-ChildItem に -Recurse を付けますが、先にコピーを取ってから実行してください(理由は次の「落とし穴」で説明します)。
方法2:Node.jsで変換する
Node.jsが入っている環境なら、次のスクリプトでも同じ処理ができます。同名のファイルがすでにある場合は、上書きせずにスキップする作りにしています。
// nfc-rename.mjs 使い方: node nfc-rename.mjs <フォルダ>
import { readdirSync, renameSync, existsSync } from "node:fs";
import { join } from "node:path";
const dir = process.argv[2];
for (const name of readdirSync(dir)) {
const nfc = name.normalize("NFC");
if (nfc === name) continue;
if (existsSync(join(dir, nfc))) {
console.log(`SKIP (same name exists): ${JSON.stringify(name)}`);
continue;
}
renameSync(join(dir, name), join(dir, nfc));
console.log(`OK: ${name.length} -> ${nfc.length} chars`);
}
このスクリプトの動作確認はWindowsで行っています。Mac上で実行したときの挙動(Macのファイルシステムが正規化の違いをどう扱うか)は検証していないため、Mac側で使う場合は、必ずコピーしたフォルダで試してください。
方法3:専用ソフトを使う
NFDからNFCへの変換に対応したファイル名変換ソフトもあります(例として、BandiNamerが紹介されています)。コマンド操作に抵抗がある場合の選択肢ですが、提供状況や対応OSは公式ページで確認してください。
他所ではあまり書かれていない落とし穴
変換方法はよく紹介されていますが、実務で困るのは変換したあとや、変換する前の判断です。
落とし穴1:同じ名前のNFDとNFCが同じフォルダに共存する
WindowsのNTFSでは、見た目が同じNFDとNFCの2つのファイルが同じフォルダに併存できます。実測でも、ガ.txt(NFD)と ガ.txt(NFC)を同じフォルダに作成でき、フォルダの中身は2件として数えられました。
そのため、すでにNFCの同名ファイルがある状態でNFDのファイルをNFCにリネームすると、衝突します。PowerShellでは次のようなエラーになりました。
Cannot create a file when that file already exists.
上書きされない点は安全ですが、一括変換が途中で止まったり、「同じ名前のファイルが2つあるように見える」状態が残ったりします。Macから受け取ったフォルダに、以前自分で保存した同名ファイルが混ざっていないかを、変換前に確認してください。
落とし穴2:ファイル名が長く(バイト数が多く)なる
NFDは濁点を別の文字として持つため、NFCより文字数もバイト数も増えます。先ほどの実測では、34バイトが46バイトになりました(約1.35倍)。
ファイル名や保存先の長さに上限があるシステム(アップロード先、バックアップソフト、共有サーバーなど)では、NFCなら通る名前がNFDだと上限を超えることが考えられます。「文字数は上限以内なのにエラーになる」場合は、バイト数と濁点の数を疑ってください。どのシステムでどの上限が適用されるかは環境ごとに異なるため、実際の仕様は各システムの資料で確認が必要です。
落とし穴3:変換するとリンクや参照が切れる
ファイル名をNFCに変えると、そのファイル名を参照していたものが対象を見失います。たとえば次のようなものです。
- Excelやドキュメント内のファイルへのリンク
- HTMLやMarkdownから参照している画像のパス
- バッチ処理・スクリプトに書き込んだファイル名
- 共有サーバー上の既存URL
Webサイトの画像などで、リンク先のファイル名がNFD、リンク元の記述がNFCだと、サーバーによっては「ファイルが見つからない」になります(URLでは %E3%82%99 を含むかどうかで別のパスとして扱われるため)。ファイル名を直したら、参照側も同じ形式にそろえるのが原則です。Web公開用のファイルは、そもそも日本語名を避けて半角英数字にしておくと、この問題自体を避けられます。
落とし穴4:コピペで再びNFDが混ざる
直したつもりでも、Mac上のファイル名を文字として取り出して貼り付けると、NFDがそのまま入ることがあります。たとえば、Finderのファイル名をコピーして、フォームや表計算ソフトの検索欄に貼り付ける場合です。
見た目は同じなのに、検索でヒットしない、VLOOKUP で一致しないといった症状になります。この場合も、先ほどの文字数カウントと差分比較で原因を確認できます。文字列として貼り付けてしまった値は、文字列としてNFCに変換するか、半角英数字で打ち直すのが確実です。
なお、全角・半角が混在して照合できない場合は別の問題で、半角カナの濁点が2文字として数えられる点を含めて、全角・半角が混在したデータを一括で揃える方法で扱っています。
再発を防ぐための運用
一度直しても、Macから受け取るたびに起きるなら、運用で防ぐほうが確実です。
- やり取りするファイル名に、濁点を含む日本語を使わない(半角英数字とハイフンにする)
- 受け取った側で、フォルダごとに一括でNFC化してから使う(コピーを取ってから)
- システムに登録するファイル名は、登録前に文字数・バイト数で確認する
- ZIPで渡す場合は、受け取り側の環境で正しく展開できるか、事前に1件だけ試す
Git管理するプロジェクトでは、macOSとの併用時にファイル名の正規化が問題になることがあり、core.precomposeunicode という設定が用意されています。通常はMac版のGitが自動で設定するとされていますが、チーム内にMacとWindowsが混在している場合は、設定値を確認しておくと安心です(詳細はGitの公式ドキュメントをご確認ください)。
まとめ
- 濁点が分離して見えるのは、NFD(分解)とNFC(合成)の違いで、データが壊れているわけではない
- 見た目では判断できないので、文字数カウント、差分比較、URLエンコードで確認する
- 直すときは、PowerShellやNode.jsでNFCに変換する。実行前にフォルダのコピーを取る
- 落とし穴は、同名ファイルの衝突、バイト数の増加、参照の切れ、コピペによる再混入
- 再発を防ぐには、やり取りするファイル名を半角英数字にするのが最も確実
この記事は、一般的な整理と筆者の動作確認(Windows上)に基づくものです。ご利用の環境(Macのバージョン、ファイルシステム、共有サービス)によって挙動が異なる場合があります。重要なファイルを扱う前には、必ずバックアップを取ってから作業してください。