子目录未被搜到是因为误用dirs = [...]而非dirs[:] = [...]原地修改;正则应预编译,文件名匹配优先,内容匹配需判文本、限大小、捕异常;windows下注意大小写和长路径。

用 os.walk 遍历目录时,为什么子目录没被搜到?
常见原因是调用了 os.walk 后没正确处理返回的三元组,或误用了 topdown=True 时提前修改了 dirs 列表但没意识到它影响后续遍历。
实际遍历时必须保留 root、dirs、files 三者对应关系;若需跳过某些子目录(比如 .git),应在原地修改 dirs 列表(不是重新赋值):
for root, dirs, files in os.walk(path):
# 跳过 .git 目录
dirs[:] = [d for d in dirs if d != '.git'] # 注意 [:] 原地替换
for f in files:
full_path = os.path.join(root, f)
直接写 dirs = [...] 不会生效,因为 os.walk 内部只读取原始引用。
正则匹配文件名还是文件内容?选错场景会极大拖慢速度
用 re.search 匹配文件名是轻量操作,适合快速筛选;但若对每个文件都用 open().read() 做全文正则匹配,I/O 和内存开销会陡增,尤其遇到大日志或二进制文件时容易卡死或爆内存。
建议按需分层处理:
- 先用
os.path.basename+ 正则快速过滤文件名(如r'.*.py$') - 再对命中的小范围文件做内容扫描,且务必加
try/except捕获UnicodeDecodeError - 对超大文件(>10MB)跳过内容搜索,或改用流式读取 +
re.finditer分块匹配
示例中判断是否可读文本:
def is_text_file(path):
try:
with open(path, 'rb') as f:
return b' ' not in f.read(1024) # 有 null 字节大概率是二进制
except (OSError, IOError):
return False
re.compile 提前编译正则,否则在循环里反复编译是隐形性能杀手
如果搜索逻辑放在 os.walk 循环内部,且每次调用 re.search(pattern, ...) 传入的是字符串而非已编译对象,CPython 会为同一 pattern 缓存一次,但多线程或复杂 pattern 下缓存失效风险高,且可读性差。
明确写出编译步骤,既提速又便于调试:
name_pattern = re.compile(r'^test_.*.py$') content_pattern = re.compile(r'raises+Exception', re.MULTILINE) <p>for root, dirs, files in os.walk(path): for f in files: if name_pattern.match(f): # 文件名匹配 fp = os.path.join(root, f) if is_text_file(fp): try: with open(fp, encoding='utf-8') as fin: if content_pattern.search(fin.read()): print(fp) except UnicodeDecodeError: pass</p>
注意:文件内容匹配时,re.MULTILINE 让 ^/$ 匹配每行首尾,不是整个字符串首尾。
Windows 路径分隔符和大小写敏感问题,不处理好就搜不到东西
Windows 默认不区分文件名大小写,但 os.walk 返回的路径是原始大小写;而正则默认区分大小写。例如用 r'.*.PY$' 在 Windows 上搜不到 main.py。
解决方案取决于需求:
- 统一转小写比对:
if name_pattern.search(f.lower()) - 正则加
re.IGNORECASE标志(推荐):re.compile(r'.*.py$', re.IGNORECASE) - 路径拼接始终用
os.path.join,别硬写'\'或'/'
另外,Windows 对长路径(>260 字符)有限制,启用 \? 前缀可绕过,但需确保 Python 版本 ≥3.6 且路径为绝对路径:
if os.name == 'nt':
path = r'\?' + os.path.abspath(path)
实际用起来最易忽略的是编码错误导致的静默跳过,以及未限制文件大小引发的 OOM —— 这两个点不加防护,工具在真实项目里基本不可靠。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











