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)参数说明
三、返回值说明
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()是最常用的目录遍历工具,自动递归遍历子目录 -
返回三元组
(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()更灵活。
本文涉及AI创作
内容由AI创作,请仔细甄别