当前位置:首页 > 文章列表 > 文章 > python教程 > Python pathlib.rglob递归查找文件时为什么漏掉隐藏目录怎样在批处理代码中减少额外分配

Python pathlib.rglob递归查找文件时为什么漏掉隐藏目录怎样在批处理代码中减少额外分配

来源:17golang原创 2026-11-10 05:14:24 0浏览 收藏

如果你用 Path.rglob() 扫描项目目录,发现结果里没有某个以点号开头的目录,先不要把原因归结为“pathlib 会忽略隐藏目录”。Python 官方文档明确说明,pathlib 中以点号开头的文件名并不特殊;更常见的原因是权限错误被扫描器抑制、目录其实是符号链接,或者后续代码把结果转成列表并做了额外过滤。

官方地址:https://docs.python.org/3/library/pathlib.html

这篇只解决一个批处理场景:递归找文件时怎样确认“漏掉”的真实边界,并让大量结果按需流过处理函数,减少一次性分配。

先确认:pathlib 不会自动排除点号目录

rglob(pattern) 相当于在递归 glob 的前面补上 **/。对于 Path 和 PurePath,点号并没有像传统 shell 通配规则那样获得特殊待遇,所以 root.rglob("*.json") 的匹配范围可以包含 .cache/data.json。返回顺序没有保证,需要顺序时再显式排序。

pathlib rglob 的匹配边界、隐藏目录、权限扫描和符号链接关系说明图
图1:结构说明图,展示 rglob 的模式范围与点号目录、权限边界、符号链接之间的关系;这是静态说明图,不是运行截图。

因此,下面这种写法通常没有必要:

from pathlib import Path

root = Path("data")

# pathlib 不把点号目录当成特殊目录,先按文件名模式递归查找
for path in root.rglob("*.json"):
    # 只保留普通文件,避免把目录匹配结果交给后续解析器
    if path.is_file():
        print(path)

如果目标是“包含隐藏目录”,不需要额外拼接一个 .* 分支。反过来,如果你使用的是 glob.glob(),再把它的隐藏文件规则直接套到 pathlib 上,才容易产生错误判断。

结果缺失时,优先排查三个真实边界

第一类是权限。官方文档说明,扫描目录时出现的 OSError(包括部分 PermissionError)可能被 glob() 和 rglob() 抑制,调用方只会看到“少了一些路径”。第二类是符号链接:递归展开 ** 时默认不跟随符号链接目录,避免意外进入环路。第三类是模式范围,例如只匹配 *.json 时,扩展名不符合的文件当然不会出现。

可以按这个顺序判断:先确认目标目录是否可读,再确认它是不是指向其他位置的链接,最后把实际传入的 pattern 和后续过滤条件单独记录。不要先把 rglob() 的结果用 list() 固化,因为那会同时掩盖扫描耗时和内存增长。

批处理不要先 list:让 Path 对象按需流过循环

rglob() 返回可迭代结果。批处理通常只需要“找到一个就处理一个”,不需要把所有路径同时留在内存中:

from pathlib import Path
from collections.abc import Iterator

def iter_json_files(root: Path) -> Iterator[Path]:
    # 直接返回迭代器,避免一次性创建完整路径列表
    for path in root.rglob("*.json"):
        # is_file 让目录名不会进入文件解析阶段
        if path.is_file():
            yield path

def consume(root: Path) -> None:
    # 消费一个处理一个,处理完后不保留全量 Path 引用
    for path in iter_json_files(root):
        text = path.read_text(encoding="utf-8")
        # 这里放单个文件的解析、入库或发送逻辑
        handle_record(path.name, text)

这个写法减少的是“结果集合”的额外分配,不代表磁盘扫描本身没有成本。不要在循环里反复调用 str(path)、resolve() 或把路径复制到多个中间列表;只有日志、序列化或接口参数确实需要字符串时再转换。若业务只关心后缀,尽量把条件放在 glob 模式中,而不是先匹配所有路径再二次筛选。

需要剪枝和看见错误时,用 Path.walk

当目录树很大,或者你必须跳过 .git、缓存目录,同时又想知道哪一级扫描失败,Path.walk() 更适合表达这个边界。它会把当前目录、子目录名和文件名分开交给调用方;在自顶向下遍历时,可以原地修改目录名列表来剪枝。

Path.walk 剪枝、错误回调与批处理消费者减少额外分配的关系说明图
图2:结构说明图,展示目录遍历、剪枝策略、错误回调与按需消费者的静态关系;这是结果示意图,不是运行截图。
from pathlib import Path

def report_scan_error(error: OSError) -> None:
    # 保留目录名和错误类型,方便区分权限问题与模式问题
    print(f"扫描失败: {error.filename} ({type(error).__name__})")

def iter_json_files(root: Path):
    for directory, dirnames, filenames in root.walk(on_error=report_scan_error):
        # 只剪掉明确不需要的目录;点号目录不会被默认删除
        dirnames[:] = [name for name in dirnames if name not in {".git", "__pycache__"}]
        for name in filenames:
            # 先按文件名筛选,再构造最终 Path,减少无关对象参与后续处理
            if name.endswith(".json"):
                yield directory / name

如果隐藏目录本身就是业务数据,不要写成 if name.startswith(".") 的统一过滤。若必须跟随符号链接,要明确设置相应选项并防范链接回指父目录的无限递归;如果只是普通递归查找,保留默认不跟随链接的行为更容易控制范围。

一张表记住排查与优化边界

现象优先判断处理方式
点号目录中的匹配文件不见了后续过滤或权限异常检查过滤条件,必要时用 Path.walk(on_error=...)
链接目录没有继续深入默认不递归符号链接确认是否真的需要跟随,并防止环路
内存随文件数增长调用了 list(rglob(...))直接迭代生成器,避免全量保存

结论很简单:rglob() 本身不是“隐藏目录过滤器”。先区分点号命名、权限、符号链接和模式范围,再决定继续用 rglob(),还是换成能剪枝并显式接收错误的 Path.walk()。批处理侧则坚持按需消费,通常比盲目优化字符串转换更值得优先处理。

相关问题

为什么要对 rglob 结果排序?因为官方文档不保证返回顺序;只有下游需要稳定顺序时才排序,否则会额外创建排序后的集合。

什么时候应该用 walk 而不是 rglob?需要剪枝、记录扫描错误、区分目录和文件名时用 walk() 更直观;只需匹配一个模式并按需消费时,rglob() 更简洁。

版本声明
本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
Python pathlib.rglob递归查找文件时为什么漏掉隐藏目录为什么结果为空或不符合预期Python pathlib.rglob递归查找文件时为什么漏掉隐藏目录为什么结果为空或不符合预期
上一篇
Python pathlib.rglob递归查找文件时为什么漏掉隐藏目录为什么结果为空或不符合预期
Python dataclass slots怎样减少大量数据对象的实例内存怎样完成一个可复用的最小示例
下一篇
Python dataclass slots怎样减少大量数据对象的实例内存怎样完成一个可复用的最小示例
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    543次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    516次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    500次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    485次学习
查看更多
AI推荐
  • PubMedQA数据集详解:生物医学问答基准、功能与应用指南
    PubMedQA
    深入了解PubMedQA生物医学问答数据集,涵盖其核心功能、使用方法及在临床决策、药物研发等场景的应用,助力提升NLP模型性能。
    965次使用
  • H2O EvalGPT:开源LLM大模型评估与排行榜工具
    H2O EvalGPT
    H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
    966次使用
  • LMArena是什么?伯克利AI模型评估平台使用指南与功能解析
    LMArena
    LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
    1077次使用
  • 斯坦福HELM:大语言模型Holistic Evaluation整体评估框架详解
    HELM
    深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
    1057次使用
  • MMBench详解:多模态大模型基准测试、功能特点与使用指南
    MMBench
    MMBench是由上海人工智能实验室等机构联合推出的多模态基准测试平台,提供细粒度能力评估、大规模数据集及VLMEvalKit工具。本文详细介绍其核心功能、安装使用方法及应用场景,助力开发者全面评估多模态模型性能。
    888次使用
微信登录更方便
  • 密码登录
  • 注册账号
登录即同意 用户协议 和 隐私政策
返回登录
  • 重置密码