以下の記事の続編。
- NASの暗号化フォルダはeCryptfsを使っており、ファイル名に143バイト制限がある
- Macのファイル名の多く*1はApple Modified NFD
- MacからNASにSMB経由で持っていくとファイル名がNFCになる
そこで、NFCを適用した上で140バイト超になるファイル名を事前に知りたい。
以前紹介したワンライナー(の改変)。
find . | while IFS= read -r l; do c=$(printf '%s' "${l##*/}" | wc -c); [[ $c -gt 140 ]] && echo "$c" "$l"; done
これだとNFDのままでのカウントになるため、実際にはセーフな長さのファイル名も抽出してしまっていた。
ファイル名にNFCを適用したい
ただ単にNFCを適用すると一部の文字が別の字体に変わってしまうらしい[1]。
安全なNFC(バイト数をカウントするだけだったら不要かもしれないが)を適用した上で140バイト超になるファイル名を抽出するワンライナー[2][3]。
find . | while IFS= read -r l; do c=$(printf '%s' "${l##*/}" | perl -C -MUnicode::Normalize -pe 's/(\P{CompEx}+)/NFC($1)/eg' | wc -c); [[ $c -gt 140 ]] && echo "$c" "$l"; done
iconvを使わない理由
macOS版iconvにはサロゲートペアの文字の変換にバグがあるため[4]。
Apple Modified NFDが除外する符号位置
Apple Modified NFDでどの文字を置換しないかは[5]。時間があったら本当かどうかCFStringGetFileSystemRepresentationを叩いて[6]調べてみる*2。
参考文献
[1] 結合文字列をUnicode正規化で合成する方法の危険性 #Unicode - Qiita
[2] ファイル名に NFD 文字を含むファイルをリストアップするワンライナー - Neo's World
[3] 結合文字列を合成する安全な方法を考える #Perl - Qiita
[4] macOS iconv(3) UTF-8-MAC エンコーディングの問題 - OSSTech Advent Calendar 2019 - ダメ出し Blog
[6] PyObjC で Modified NFD を再現する #Python - Qiita