コラムのお題を考えるとき、内容が重複しないよう連載第1回からの見出しをざっとチェックしているのだが、なぜこれほど重要なことを取りあげてこなかったか、と反省することも少なくない。今回は、濁点(゛)や半濁点(゜)が付く文字を含むファイル/フォルダ名をTerminal上で扱うときの問題と対策、というかなり昔から存在するテーマについて考えてみたい。

「ダ」や「パ」を含むファイルを検索できない理由

まず、具体事例から説明しよう。カレントディレクトリに「オランダ」と「パナマ」、「ニホン」という名前のPNGファイルがあるとして、以下に示す図のとおりfindコマンドでファイル検索したとする。そのとき、ヒットするのは「ニホン」だけ。lsコマンドを実行すると確かに存在するし、綴りに誤りがあるわけでもなく、ただ濁点・半濁点を使うカナ(日本語IMEで入力)を検索語としただけなのに、ヒットしないのだ。

ファイル名に誤りはないはずなのに、濁点・半濁点が含まれるファイルはヒットしない

この問題は、コピー&ペーストで解決する。lsコマンドで出力されたファイル名をコピーし、findコマンドの引数部分にペーストすると、今度はあっけなくヒットするのだ。つまり、日本語IMEで入力した「パナマ」とコピペした「パナマ」は別モノということ。Terminalに限らず、Finderに表示されたファイル/フォルダ名でもまったく同じ現象が起こる。

テキストエディタにその似て非なる2つの文字列をペーストすれば、両者の違いがよくわかる。たとえば、開発者御用達のテキストエディタ「Sublime」で試すと、濁点・半濁点を意味する記号がカナ本体と2文字に分かれていることを確認できるはず。TextEdit.appやNotes.appでは1文字に見えるのに……。

lsコマンドの結果をコピーして「Sublime」にペーストすると、濁点・半濁点の処理が異なることがわかる

その答えは「NFD(Normalization Form Canonical Decompression)」だ。NFDはUnicodeにおける正規化方式のひとつで、日本語においてはカナの濁点・半濁点、欧米諸語ではウムラウトなどの記号を文字本体と分離したうえで符合化する。一方、Windowsなど他のOSでは、濁点や半濁点を含む文字を分離せず1文字として扱う -- 合成済の文字しか扱わないため「NFC(Normalization Form Canonical Compression)」と同じ結果になる -- ことが基本だ。前述の例でいえば、日本語IMEで入力した文字がNFCで符合化されていたために、NFDのファイル名とは別モノと判定されたと理解できる。

この問題は、OS Xで作成したファイルを他のOSへ転送するときにも顕在化する。FAT/FAT32フォーマットのUSBメモリを読み書きするときのように、NFC/NFDを相互変換するOS Xの機能が働くケースもあるが、SSH/SCPのようにそのままのことが少なくない。一方、Dropboxなどのマルチプラットフォーム指向のクラウドサービスは、おそらくクライアントOSを見て対策しているのだろう、NFC/NFDにまつわる諸問題が発生しない。結局のところ、OSの仕様は変えられないため、クライアントソフトの段階で最終的な対策を講じなければならないのだ。

なお、正確にはOS XにおけるUnicode正規化は、NFDとまったく同じではなく、一部が正規化の対象とされない(いうなれば「改変版NFD」)。かなり長くなりそうなので説明は割愛するが、RubyやEmacsなどOS Xユーザにも愛用されているソフトウェアの多くには、この改変版NFDに対応するための機能が用意されている。残念ながら、OS XのSMBクライアント(Finder)にはこの機能がなく、濁点・半濁点を含む共有ボリュームが開けないという問題がEl Capitanのいまも問題として残る。

クイックハックでUnicode正規化問題に対処する

Unicode正規化に関する問題はOS/ファイルシステムレベルの問題であり、やり取りする他のOSの事情も考慮しなければならないから、根本的な解決が難しい。前述したとおり、クライアントソフト側で対処するか、エンドユーザの創意工夫で乗り越えなければならないのが現実だ。

冒頭に挙げた「オランダ」や「パナマ」といった濁点・半濁点を含むファイルにTerminal上で対処するには、IME側で対応できれば話は別だが、そうもいかないので符合化方式を変換して対処するしかない。解決策というには苦しいクイックハックは以下のとおりで、IMEで入力した文字(オランダ.png)をechoコマンドからiconvコマンドにパイプし、UTF-8からOS X独自の改変版NFD(UTF-8-MAC)に変換、その結果をfindコマンドの引数とするというものだ。手間のかかる話だが、これでfindコマンドで濁点・半濁点を含むファイルの検索が可能になる。

$ find . -name `echo "オランダ.png" | iconv -f UTF8 -t UTF8-MAC`

iconvコマンドで文字列をNFD(改変版)に変換し、findコマンドの引数に与えると、IMEから入力した濁点・半濁点を含む文字列で検索できる

マウントしたSMB共有領域で濁点・半濁点を含むフォルダが開けないという問題については、mount_smbfsコマンドを使い手動でマウントするという手がある。ただし、共有ボリューム名をUTF-8で符合化しなければならないため、準備には多少の手間が必要だ。以下の例では、IPアドレスが192.168.12.10のホスト上にある「ライブラリ」という共有ボリューム名を指定しているが、このとおり一見では理解できないものとなっている。URL エンコード(符号化)/デコード(復号)ツールなど支援ツールを活用しつつ、試してほしい。

$ mount_smbfs //userID:PASSWORD@192.168.12.10/%E3%83%A9%E3%82%A4%E3%83%96%E3%83%A9%E3%83%AA