pin_drop当前位置:知识文库 ❯ 图文

os.walk()遍历目录树用法详解 - Python文件操作教程

一、os.walk()概述

os.walk()是Python中最强大的目录遍历工具,它递归遍历目录树,每次迭代返回一个三元组(current_dir, subdirs, files),可以方便地处理整个目录结构。无论是统计文件数量、查找特定类型的文件,还是批量处理目录中的内容,os.walk()都是首选方案。


二、语法与参数详解

代码示例

os.walk(top, topdown=True, onerror=None, followlinks=False)

参数说明

参数 类型 说明
top str | bytes 遍历的起始目录路径
topdown bool True为先遍历顶层再遍历子目录(默认),False相反
onerror Callable 错误处理回调函数,默认为None
followlinks bool 是否跟随符号链接,默认False

三、返回值说明

os.walk()返回一个生成器,每次产生三元组(dirpath, dirnames, filenames)

  • dirpath:当前遍历到的目录路径字符串

  • dirnames:当前目录下的子目录名称列表(不包含路径)

  • filenames:当前目录下的文件名称列表(不包含路径)


四、代码示例

示例1:遍历目录树

代码示例

import os

for dirpath, dirnames, filenames in os.walk('my_project'):
    print(f"目录: {dirpath}")
    for d in dirnames:
        print(f"  [目录] {d}")
    for f in filenames:
        print(f"  [文件] {f}")

输出:

代码示例

目录: my_project
  [目录] src
  [目录] docs
  [文件] README.md
目录: my_project/src
  [文件] main.py
  [文件] utils.py
目录: my_project/docs
  [文件] guide.md

示例2:统计目录树中的文件数量和总大小

代码示例

import os

total_files = 0
total_size = 0

for dirpath, dirnames, filenames in os.walk('.'):
    for f in filenames:
        total_files += 1
        filepath = os.path.join(dirpath, f)
        try:
            total_size += os.path.getsize(filepath)
        except OSError:
            pass

print(f"文件总数: {total_files}")
print(f"总大小: {total_size / 1024 / 1024:.2f} MB")

输出:

代码示例

文件总数: 42
总大小: 3.56 MB

示例3:查找特定类型的文件

代码示例

import os

def find_files(root_dir, extension):
    """查找指定扩展名的所有文件"""
    results = []
    for dirpath, dirnames, filenames in os.walk(root_dir):
        for f in filenames:
            if f.endswith(extension):
                results.append(os.path.join(dirpath, f))
    return results

# 查找所有Python文件
py_files = find_files('.', '.py')
print(f"找到 {len(py_files)} 个Python文件:")
for f in py_files[:5]:
    print(f"  {f}")

输出:

代码示例

找到 12 个Python文件:
  .\main.py
  .\src\app.py
  .\src\utils.py

示例4:通过修改dirnames跳过特定目录

代码示例

import os

# 跳过隐藏目录和__pycache__目录
for dirpath, dirnames, filenames in os.walk('.'):
    # 原地修改dirnames,过滤掉不需要的目录
    dirnames[:] = [d for d in dirnames if not d.startswith('.') and d != '__pycache__']
    print(f"遍历: {dirpath}")
    for f in filenames:
        print(f"  文件: {f}")

通过在循环中修改dirnames列表,可以控制os.walk()的遍历行为,删除某个目录名即可跳过该子目录的遍历。


五、实际应用场景

  • 场景1:在项目构建中,遍历源码目录收集所有源文件

  • 场景2:在文件搜索中,递归查找特定名称或类型的文件

  • 场景3:在目录同步中,比较两个目录树的差异


六、注意事项

注意os.walk()是生成器,不会一次性加载所有结果到内存,适合大目录遍历。

注意:修改dirnames列表可以控制遍历行为,删除某个目录名可跳过该子目录。

注意topdown=False时先遍历子目录再遍历父目录,适合删除操作。


七、目录遍历方法对比

方法 递归 内存效率 灵活性
os.walk() 自动递归 高(生成器)
os.listdir()递归 手动递归 中等
os.scandir()递归 手动递归 最高 最高
pathlib.Path.rglob() 自动递归

八、小结

  • os.walk()是最常用的目录遍历工具,自动递归遍历子目录

  • 返回三元组(dirpath, dirnames, filenames),清晰区分目录和文件

  • 是生成器,内存效率高,适合遍历大型目录树


九、练习题

练习1

编写程序,使用os.walk()统计指定目录下各扩展名文件的数量。

参考答案:

代码示例

import os
from collections import defaultdict

def count_files_by_extension(root_dir):
    ext_count = defaultdict(int)
    for dirpath, dirnames, filenames in os.walk(root_dir):
        for f in filenames:
            ext = os.path.splitext(f)[1] or '(无扩展名)'
            ext_count[ext] += 1
    return dict(ext_count)

result = count_files_by_extension('.')
for ext, count in sorted(result.items(), key=lambda x: x[1], reverse=True):
    print(f"{ext}: {count} 个文件")

练习2

编写函数,使用os.walk()找出目录树中最近7天内修改过的所有文件。

参考答案:

代码示例

import os
import time

def find_recent_files(root_dir, days=7):
    """查找最近N天内修改过的文件"""
    cutoff_time = time.time() - (days * 24 * 60 * 60)
    recent_files = []
    
    for dirpath, dirnames, filenames in os.walk(root_dir):
        for f in filenames:
            filepath = os.path.join(dirpath, f)
            try:
                mtime = os.path.getmtime(filepath)
                if mtime >= cutoff_time:
                    recent_files.append(filepath)
            except OSError:
                pass
    return recent_files

# 使用示例
recent = find_recent_files('.', 7)
print(f"最近7天修改的文件: {len(recent)} 个")
for f in recent[:5]:
    print(f"  {f}")

十、常见问题FAQ

常见问题

os.walk()和os.listdir()有什么区别?

os.listdir()只返回当前目录下的文件和子目录名称列表,不递归遍历;而os.walk()会自动递归遍历整个目录树,每次迭代返回当前目录路径、子目录列表和文件列表。对于需要处理多级目录的场景,os.walk()更加方便。

topdown=True和topdown=False有什么区别?

topdown=True(默认)表示先遍历父目录再遍历子目录,此时可以修改dirnames来控制遍历行为;topdown=False表示先遍历子目录再遍历父目录,适合删除操作,因为删除子目录后再处理父目录更安全。

如何在遍历过程中跳过某些目录?

可以通过原地修改dirnames列表来实现,例如:dirnames[:] = [d for d in dirnames if d != 'skip_dir']。注意必须使用原地修改(dirnames[:]),不能直接赋值(dirnames = ...),否则不会影响遍历行为。

os.walk()遇到权限错误会怎样?

默认情况下,os.walk()遇到权限错误会忽略该目录继续遍历。如果需要自定义错误处理,可以传入onerror参数,例如:os.walk('.', onerror=lambda e: print(f"错误: {e}"))。

os.walk()和pathlib.Path.rglob()哪个更好?

两者各有优势:os.walk()返回结构化的三元组,适合需要同时处理目录和文件的场景;pathlib.rglob()更简洁,适合查找特定模式的文件。对于简单的文件搜索,rglob更优雅;对于复杂的目录操作,os.walk()更灵活。

标签: os.walk 目录遍历 Python教程 文件操作 递归遍历 生成器

本文涉及AI创作

内容由AI创作,请仔细甄别

list快速访问

上一篇: Python os.stat()获取文件信息用法详解 - 大小时间与权限 下一篇: os.environ环境变量操作详解 - Python配置管理教程

poll相关推荐