#!/usr/bin/env python3"""NFC と一致しないファイル名を数えて一覧にする。読み取り専用。"""import os, sys, unicodedataroot = sys.argv[1] if len(sys.argv) > 1 else "."skip = {"node_modules", ".git"} # 巨大で、日本語名を探す対象でもないtotal = non_ascii = decomposed = 0for cur, dirs, files in os.walk(root): dirs[:] = [d for d in dirs if d not in skip] # 降りる前に枝を落とす for name in dirs + files: total += 1 if name.isascii(): continue # 英数字だけの名前は対象外 non_ascii += 1 if unicodedata.normalize("NFC", name) != name: decomposed += 1 print("NFD:", os.path.join(cur, name))print(f"total={total} non_ascii={non_ascii} decomposed={decomposed}")
dirs[:] = ... と書くのは、os.walk に「この枝には降りない」と伝えるためです。単に if で飛ばすだけでは、node_modules の中を歩き続けてしまいます。
手順2: 探す側に正規化を一行足す
名前を直さなくても、探す側を揃えれば取りこぼしは防げます。
import os, unicodedatadef find_by_name(root, wanted): """NFC/NFD の違いを無視して、名前が一致するパスを返す。""" key = unicodedata.normalize("NFC", wanted) hits = [] for cur, dirs, files in os.walk(root): for name in files: # ディスク上の名前を NFC に揃えてから比べる if unicodedata.normalize("NFC", name) == key: hits.append(os.path.join(cur, name)) return hits