先日,NAS (SAMBA) にあるファイル(フォルダ)が Mac から見えないという事象に遭遇しました。どうやら,Unicode の正規化形式に起因する問題であったようです。文字コードの正規化形式を変換して解決しました。
症状と原因
まず,今回の障害の症状と原因を整理しておきます。
症状
- NAS (SAMBA) に保存されている一部のファイルが,Mac PC から見えない
- 同ファイルは,Windows/Linux からは見えている
原因
どうやら,このファイルのファイル名に使われている文字コード(正確には正規化方式)が NFD 形式であったためのようです。所謂,NFC/NFD問題(Unicode正規化形式の違いに起因する問題)と呼ばれるもので,MacOS で作成したファイルで起こりがちなようです。
NFD → NFC 変換
問題解決のために,ファイルの名前を UTF-8 (NFC) 形式に変換する Python のプログラムを作成しました。奥村晴彦さんのページを参考にしています。当プログラムを起動すると,起動プログラムと同じ階層とそれ以下の階層にあるファイル(フォルダ)の名称を UTF-8 (NFC) 形式に変換します。
import os
import pathlib
import unicodedata
files = pathlib.Path('.').glob('**/*')
for file in files:
filename = str(file)
nfc_filename = unicodedata.normalize('NFC', filename)
if filename != nfc_filename:
print('Renaming ', filename.encode('utf-8'), 'to ', nfc_filename.encode('utf-8'))
os.rename(filename, nfc_filename)
テストしてみます。
まず,テストに使用する NFC/NFD 形式のファイルを作成します。次のプログラムで作成できます。
import os
import unicodedata
s = 'ヴィジブル'
s_nfc = unicodedata.normalize('NFC', s).encode('utf-8')
os.makedirs('nfc_files', exist_ok=True)
os.chdir('nfc_files')
with open(s_nfc, 'w') as f:
pass
import os
import unicodedata
s = 'インヴィジブル'
s_nfd = unicodedata.normalize('NFD', s).encode('utf-8')
os.makedirs('nfd_files', exist_ok=True)
os.chdir('nfd_files')
with open(s_nfd, 'w') as f:
pass
NFC 形式の「ヴィジブル」と NFD 形式の「インヴィジブル」という名称のファイルが生成されます。この状態で Mac PC から NAS (SAMBA) にアクセスしても「ヴィジブル」しか見えません(今回の障害の主題です)。
先ほどの変換プログラムを実行してみます。
python rename_to_nfc.py
これですべてのファイルがNFC 形式に統一されたので「インヴィジブル」も見えるようになりました。
以上,Mac PC から NAS (SAMBA) のファイルが見えない問題を,文字コードの正規化形式を変換して解決しました。
NAS のマウント
話が前後しますが,そもそも NAS (SMB) にアクセスして上記の変換プログラムを起動するためには,ローカル PC にマウントできていなければならないはずです。NAS のマウントは以下のようにして行います。
MacOS の場合:
mount -t smbfs //user@smbserver/share ~/mnt/smb
Linux の場合:
sudo mount -t cifs -o uid=$(id -u),gid=$(id -g),username=user //smbserver/share ~/mnt/smb
感想
Unicode 正規化方式として NFD を採用しているのは Mac なのに,SMB (NAS) を介してみると当の Mac だけがそういったファイルを認識できない(ことがある)というのはなんとも皮肉な結果ですね...。