Watch at Ease看見世界,讀懂生活。

科技 · 實用指南

Pathlib 總能找到隱藏檔案?應剪枝走訪,而不是事後過濾

結果過濾發生在 Python 已進入目錄之後。先定義「隱藏」規則,自頂向下剪枝,再核對真正未被走訪的樹。

Original diagram comparing a pathlib result filter that still enters a hidden subtree with top-down pruning that prevents descent.
原创示意图:事後過濾仍進入隱藏子樹,剪枝則不會。 Watch at Ease

Pathlib 不把點號開頭名稱視為通用排除規則;其 glob 可匹配點檔案,而 glob.glob 另有 include_hidden。rglob 回傳後才捨棄路徑,只會隱藏結果,不會阻止 Python 進入目錄列舉後代。

掃描前先寫清策略:隱藏是 POSIX 點號前綴、Windows 隱藏屬性、應用快取名稱,或其組合?再用自頂向下走訪,在進入前從 dirnames 移除目錄,另行過濾檔案並保存走訪、跳過、連結與錯誤台帳。

先寫隱藏檔案合約

記錄根目錄、平台、Python 版本與目的。說明點號規則作用於檔案、目錄或兩者,是否納入 Windows 隱藏屬性,以及 build、vendor 等應用排除。

未實際檢查各平台中繼資料,就不要宣稱單一規則跨平台。共享應用策略可以,但平台判斷要顯式。

進入前剪除目錄

Python 3.12+ 使用 root.walk(top_down=True),逐一保留允許的子目錄並以切片寫回 dirnames;移除者不會被進入。

舊版可用 os.walk(topdown=True)。僅重新綁定變數不會改變 walker 佇列,必須原地修改。

分開過濾檔案並說明 glob 差異

目錄剪枝後才用同一策略檢查檔名,處理 .DS_Store 等葉檔案。檔案過濾不等於子樹剪枝。

若用 glob.glob,顯式記錄 include_hidden。兩個 API 都有 * 與 **,不代表隱藏項預設相同;遞迴也可能很昂貴。

明確處理 Windows 屬性與連結

Windows 上以受支援的呼叫檢查 FILE_ATTRIBUTE_HIDDEN。點號命名慣例與作業系統屬性是不同訊號。

預設不跟隨目錄符號連結;必須跟隨時記錄穩定身分並拒絕重複,避免 symlink 或 junction 循環。

以驗收清單保存錯誤與跳過

on_error 要記錄路徑、操作與例外,並決定權限錯誤是否使掃描失敗、標記不完整或允許跳過,不能靜默吞掉。

驗收清單包含根、策略版本、走訪目錄數、產出檔案數、跳過原因、連結策略與錯誤;以小型 fixture 做回歸。

Original decision diagram separating dot-prefixed names, Windows hidden attributes, and application-specific exclusions.
原创示意图:分開點號名稱、Windows 屬性與應用規則。 Watch at Ease