glob默认忽略以点开头的隐藏文件,因其遵循posix shell通配规则;需用"."或".?"显式匹配,递归搜索用"*/.",pathlib更可控,正则匹配推荐re.compile预编译。

Python用glob读不到以点开头的隐藏文件?
默认情况下,glob.glob() 和 glob.iglob() **完全忽略**以点(.)开头的文件和目录,无论操作系统是 Linux、macOS 还是 Windows(只要文件系统支持隐藏语义)。这不是 bug,是 glob 的 POSIX 兼容设计:它模仿 shell 的通配行为,而 shell 中 * 默认也不匹配点文件。
- 想匹配
.env、.gitignore,直接写glob.glob(".*")是错的——它只匹配当前目录下「名字恰好是两个字符、且都以点开头」的项(比如.a),不是你想要的「所有点文件」 - 正确做法是显式写出点前缀:
glob.glob(".*")可以,但更安全的是glob.glob(".?*")或glob.glob(".[^.]*")(避开.和..) - 如果要递归搜索子目录里的隐藏文件,得加
recursive=True并配合**:glob.glob("**/.*", recursive=True),但注意这仍不会进入.git这类隐藏目录——glob不自动跳过或进入隐藏目录,它只管路径名匹配
用pathlib替代glob处理隐藏文件更可控
pathlib.Path.rglob() 和 .glob() 默认行为跟 glob 模块一致:不匹配点文件。但它允许你手动控制遍历逻辑,避免漏掉关键隐藏项。
- 想列出当前目录所有隐藏文件(不含
.和..):[p for p in Path(".").iterdir() if p.name.startswith(".") and not p.name in {".", ".."}] - 递归找所有
.py文件,包括隐藏目录下的:[p for p in Path(".").rglob("*.py") if not any(part.startswith(".") for part in p.parts)]—— 这里反向过滤掉路径中含隐藏目录的部分;若要「包含」隐藏目录,则不用过滤,直接Path(".").rglob("*.py")即可 - 性能上,
pathlib遍历比glob稍慢一点,但可读性和调试性高很多;尤其当你要对每个路径做条件判断时,别硬套glob通配符
正则匹配特定前缀(如.env*)别用glob硬凑
glob 的通配符能力有限:*、?、[...],不支持正则里的 ^、$、分组或量词。想精确匹配 .env、.env.local、.env.production 但排除 .envrc,用 glob 写模式极易出错或漏判。
- 错误示例:
glob.glob(".env*")会误中.envrc、.env.bak等非目标文件 - 推荐组合:
pathlib+re.match():[p for p in Path(".").rglob("*") if re.match(r"\.env(\.local|\.production)?$", p.name)] - 注意
re.match()是从头匹配,所以正则必须以^开头(上面例子省略了,因为p.name就是完整文件名);若用re.search(),记得加^和$锚定 - 如果大量匹配,把正则编译一次再复用:
env_pattern = re.compile(r"\.env(\.local|\.production)?$"),然后env_pattern.match(p.name)
Windows 上隐藏文件的特殊处理
Windows 的「隐藏属性」和 Unix-like 系统的「点前缀」是两套机制。glob 和 pathlib **只看文件名,不管文件系统隐藏属性**。也就是说,一个在 Windows 资源管理器里被设为“隐藏”的 config.txt(名字不带点),glob 照样能扫到;反过来,.bashrc 在 Windows WSL 或 Git Bash 里仍是点文件,glob 默认照样忽略。
- 真要检查 Windows 文件隐藏属性,得用
os.stat().st_file_attributes(仅 Windows)或win32api.GetFileAttributes()(需 pywin32) - 跨平台脚本里,别假设「隐藏 = 点文件」;如果业务逻辑依赖隐藏属性(比如跳过备份隐藏文件),就得区分场景:Unix 看名字,Windows 看属性
- 绝大多数 Python 工具链(pip、pytest、black)只认点前缀为「隐藏」,它们不读取 Windows 属性位——所以你的脚本也优先按点前缀约定来,除非客户明确要求支持 Windows 属性
glob(".*") 能扫全所有隐藏文件,结果漏掉 .github/ 下的配置;或者在正则匹配时忘了锚定,导致前缀匹配变成子串匹配。点文件逻辑看着简单,但混合递归、跨平台、业务前缀规则后,很容易一环没兜住就出偏差。Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











