在 Python 文件与目录的批量处理场景中,我们常常需要递归地遍历一个目录下的所有子目录和文件,然后做诸如搜索、统计、重命名、删除等操作。os.walk
正是标准库中一个非常实用的工具函数,它能够帮你优雅地完成这些任务。本篇文章将从接口、参数、返回值、典型用法到进阶用法,深入剖析 os.walk
的方方面面,并给出大量代码示例,帮助你快速掌握它的使用。
os.walk
定义
os.walk(top, topdown=True, onerror=None, followlinks=False)
是 Python os
模块提供的一个生成器函数,用于递归遍历目录树。
核心作用
从指定的根目录 top
出发,按层级返回每个子目录及其文件列表,供用户在循环中依次处理。
os.walk(top,
topdown=True,
onerror=None,
followlinks=False)
参数 | 类型 | 含义 |
---|---|---|
top |
str |
必填,指定要遍历的起始目录路径 |
topdown |
bool |
可选,默认 True :先返回 top 目录,再递归子目录;若 False ,则先递归子目录后再返回 top |
onerror |
callable |
可选,遍历过程中若遇到 OSError (如权限错误)时,回调该函数并传入异常对象 |
followlinks |
bool |
可选,默认 False :遇到符号链接不进入;若设为 True ,会跟随符号链接继续遍历 |
os.walk
会返回一个 生成器,在每次循环中返回一个三元组 (dirpath, dirnames, filenames)
:
dirpath
:当前正在遍历的目录的完整路径(字符串)。dirnames
:当前目录下所有子目录名称列表(不含路径,只是名字)。filenames
:当前目录下所有非目录文件名称列表(不含路径)。Tip:如果你在循环中修改
dirnames
(增删或重排),会影响后续遍历的目录顺序或内容。
import os
root = '/path/to/project'
for dirpath, dirnames, filenames in os.walk(root):
for fname in filenames:
fullpath = os.path.join(dirpath, fname)
print(fullpath)
示例输出:
/path/to/project/main.py
/path/to/project/utils/helper.py
/path/to/project/data/sample1.txt
...
import os
def find_files_with_ext(root, ext):
matches = []
for dirpath, _, filenames in os.walk(root):
for fname in filenames:
if fname.lower().endswith(ext):
matches.append(os.path.join(dirpath, fname))
return matches
# 查找所有 .jpg 文件
jpg_list = find_files_with_ext('/path/to/images', '.jpg')
print(f"共找到 {len(jpg_list)} 张 JPG:")
for p in jpg_list:
print(" ", p)
import os
src_root = '/data/raw'
dst_root = '/data/processed'
for dirpath, _, filenames in os.walk(src_root):
rel_dir = os.path.relpath(dirpath, src_root)
target_dir = os.path.join(dst_root, rel_dir)
os.makedirs(target_dir, exist_ok=True)
for fname in filenames:
if fname.endswith('.txt'):
src_file = os.path.join(dirpath, fname)
dst_file = os.path.join(target_dir, fname)
os.rename(src_file, dst_file)
topdown=False
:后序遍历当你需要先处理最底层文件夹(例如删除空文件夹),再回到父目录时:
for dirpath, dirnames, filenames in os.walk(root, topdown=False):
# 删除所有文件
for fname in filenames:
os.remove(os.path.join(dirpath, fname))
# 如果目录空了,就删掉它
if not os.listdir(dirpath):
os.rmdir(dirpath)
onerror
:捕获遍历异常遇到无法访问的目录时,执行自定义回调,而不是直接抛错退出:
import os
def handle_error(err):
print(f"无法访问:{err.filename},跳过该目录")
for dp, dns, fns in os.walk(root, onerror=handle_error):
# 正常处理
...
followlinks=True
:跟随符号链接默认情况下,os.walk
不会进入符号链接指向的目录。若你需要遍历软链接目录,可以启用此功能(需防止循环引用):
for dp, dns, fns in os.walk(root, followlinks=True):
...
内存占用
os.walk
仅在迭代时加载当前目录内容,不会一次性把整个文件树读入内存,适合深度或海量文件遍历。
顺序可控
topdown=True
,你可以在循环体内修改 dirnames
(例如移除不想进入的子目录),从而动态剪枝。topdown=False
适用于先处理子目录再处理父目录的场景。避免符号链接循环
如果项目中存在互相指向的软链接,开启 followlinks=True
可能导致无限递归。可结合 os.path.realpath
和记录已访问路径来规避。
os.walk
是强大的目录树遍历工具,适用于搜索、统计、重命名、删除等批量文件操作。
通过 topdown
、onerror
、followlinks
等参数,你可以灵活地控制遍历顺序、异常处理和软链接跟随策略。
典型用法包括: