おさらい。 ∥ Unicode正規化 - Wikipedia
- 正規化形式
- NFC: Normalization Form Canonical Compression | 文字に何がくっついていようと、組み合わせて作られた文字であろうと、「一文字」は「一文字」じゃ。圧縮形式。Linux のファイルシステムや Windows の NTFS などが普通に使っている。
- NFD: Normalization Form Canonical Decompression | 濁点・半濁点を、あるいはウムラウト等のダイアクリティカルマークを、本体の文字とは分離してエンコードした形式。OS X の HFS+ が、これを採用してくれちゃっている。
基本としては、OS X 上に置かれるファイルは NFD であってくれて、Linux や Windows 上にあるファイルは NFC であってくれると平和で助かる。
追記(2016/09/29): コメントで指摘を頂いたんですが、確かに実際のところは HFS+ においては NFD 正規化する機能を有しているだけであって、Linux や Windows の方は慣習的に NFC 正規化されたファイル名を使っていてそれに対してファイルシステムは何の正規化もしていないだけなんですよね。私の Linux のファイルシステム中にも、うっかり NFC 正規化されたまま入れてしまってそのままになっているファイルがあります。
ファイルシステムの問題なのである
Mac OS X の HFS+ における NFD の濁点・半濁点の問題。
- HFS+ における NFD 正規化。 ∥ Mac OS Xの濁点ファイルがやってきた - miauの避難所
- Unicode正規化 - Wikipedia
結局 HFS+ を通すと、何をどうしようと NFD に正規化されてしまうんだな。NFC で格納する手だては無いと。
$ basename /Users/knaka/Desktop/パピプペポ.pdf | iconv -f utf-8-mac -t utf-8 | dm
00000000 | E3 83 91 E3 83 94 E3 83 97 E3 83 9A E3 83 9D 2E | ................
00000010 | 70 64 66 0A | pdf.
$ touch $(basename /Users/knaka/Desktop/パピプペポ.pdf | iconv -f utf-8-mac -t utf-8)
$ ll パピプペポ.pdf
表示手段
Mac ローカルでの表示に関する問題解決。基本的には、OS X 標準のツール群は、だいたい NFD について考慮してくれているようだ(あたりまえか)。なので、問題があるとしたら Homebrew などで入れたツールである。
GNU Screen
Homebrew の screen(1) も、NFD を手当てしていない。 ∥ GNU screen 最新版について - rcmdnk’s blog
なんと、OS X 標準のは、ちゃんと表示する。ただ、標準のは 256 色表示ができないのですよね。なので、手で入れます。 ∥ GNU screen 最新版について - rcmdnk’s blog
$ curl http://ftpmirror.gnu.org/screen/screen-4.2.1.tar.gz | tar zxvf -
$ cd screen-*/
$ curl https://gist.githubusercontent.com/mrkn/626040/raw/be6a04f0e64c56185ba5850415ac59dad4cd62a0/screen-utf8-nfd.patch | patch -p2
$ curl http://zuse.jp/misc/screen-utf8-osc.diff | patch -p2
$ ./configure --prefix=/usr/local --enable-colors256 && make
$ make install
転送手段
ネットワーク転送においての NFD 変換。Windows や Linux に送る際には、NFC に変換して欲しい。
Dropbox
◯: どうやら、NFC, NFD の手当てをしているみたいだ。クライアントの OS 種別は分かってますからね。さすが。
scp
✕: 何もしてくれない。
rsync
Homebrew で最新を入れれば ◯。--iconv
オプションが使えるようになる。標準(Yosemite 同梱)の方は、バージョンが上がる気配はありませんね。
$ /usr/bin/rsync --version
rsync version 2.6.9 protocol version 29
...
$ /usr/local/bin/rsync --version
rsync version 3.1.1 protocol version 31
...
$ rsync --iconv=UTF8-MAC,UTF-8 rsc-ほげ.txt svr.example.com:/tmp/
とはいえこのオプションが効くのは rsync サーバのインターフェイスを通じてのやりとりの中でのパス名についてだけですので、よく考えると当たり前なのですが、たとえば「Mac のローカルにあるディレクトリと同名のディレクトリがリモートの Linux にも有ったらフェッチする」などの場合には、「ローカルにあるディレクトリ(NFD)と同名のディレクトリがリモートにも(NFC で)有ったらフェッチする」となるので、さらに一手間が必要です。
これは Mac 上の処理:
for dirabs in /hoge/fuga/*
do
dirbase=$(basename "$dirabs")
dirbase_nfc=$(echo "$dirbase" | iconv -f UTF8-MAC -t UTF-8)
rsync ~ "svc.example.com:/foo/bar/$dirbase_nfc/" "$dirabs/"
done
コピペで ls
すると有るのに、rsync は「無いぞ無いぞ」とエラーを吐くので、しばらくハマりましたよ。面倒ね。
NFS
クライアントの Mac 側で、サーバが NFC であることを nfc
オプションで指定すれば、正しく扱える(「/etc/auto_*」については右記なども。 ∥ Using the Mac OS X Automounter - Use Your Loaf)。
$ cat /etc/auto_knaka
arc -ro,nfc nfs://luminous/mrd/arc
sftp (sshfs via FUSE)
相手の SSH サーバが NFC だとハマるかと思ったのですが、変換する仕組みがありました。助かります。
$ sshfs -o modules=iconv,from_code=UTF-8,to_code=UTF-8-MAC svc.example.com:/arc /arc
当然経路も暗号化されるし(素の NFS や CIFS だと平文を飛ばす)、個人アカウントでアクセスするから ID マップの問題も生じないし(NFS や WebDAV でハマる)で、これは良いな…。
- libfuse/libfuse: The reference implementation of the Linux FUSE (Filesystem in Userspace) interface
- osxfuse/sshfs: File system based on the SSH File Transfer Protocol
FAT な USB メモリで手渡し
「文字コードには、ローカルなコードセット(日本語の場合はCP932 Shift_JIS)が使われます」 ∥ FATファイルシステムのしくみと操作法
USB メモリ等で、なおも根強く使われ続ける FAT では、基本的に環境依存の L10N なので、ファイル名の文字コードに ASCII 以外を使えば問題が出る。今だと、NFC に揃えて zip アーカイブにでもして渡すのが正しいのだろうか。