在日常的编程工作中,我们经常需要处理文件和目录的操作。无论是数据清洗、日志分析、批量重命名,还是自动化脚本编写,遍历目录中的所有文件都是一个非常基础但又极其重要的技能。而 os 模块作为 python 标准库中与操作系统交互的核心模块,提供了强大的功能来完成这项任务。
今天,我们就来深入探讨如何使用 os 模块高效、安全地遍历目录下的所有文件,包括子目录、隐藏文件、权限控制等高级场景,并通过实际代码示例带你从入门到精通。
什么是 os 模块?
os 模块是 python 的标准库之一,它提供了一种方式来使用操作系统的功能,如文件和目录操作、环境变量管理、进程管理等。它在不同平台上(windows、linux、macos)都能保持一致的行为,是跨平台开发的理想选择。
提示:os 模块不依赖外部库,开箱即用,非常适合做系统级操作。
基础:使用 os.listdir() 遍历目录
最简单的遍历方式是使用 os.listdir() 函数。它返回指定目录下所有文件和子目录的名称列表。
import os
# 指定要遍历的目录路径
directory = "/path/to/your/folder"
# 获取目录内容
files_and_dirs = os.listdir(directory)
print("目录内容:")
for item in files_and_dirs:
print(f"📁 {item}")
注意:
os.listdir()只列出当前目录的内容,不会递归进入子目录。- 它返回的是字符串列表,包含文件名和文件夹名。
- 如果路径不存在或没有访问权限,会抛出
filenotfounderror或permissionerror。
递归遍历:os.walk() —— 真正的“全遍历”工具
如果你需要遍历一个目录及其所有子目录中的文件,os.walk() 是你的首选。它是一个生成器函数,逐层返回 (dirpath, dirnames, filenames) 三元组。
示例代码:完整递归遍历
import os
def traverse_directory(root_dir):
print(f"🔍 正在遍历目录: {root_dir}")
for dirpath, dirnames, filenames in os.walk(root_dir):
# 打印当前目录路径
print(f"📂 当前目录: {dirpath}")
# 打印所有文件
for filename in filenames:
file_path = os.path.join(dirpath, filename)
print(f"📄 文件: {file_path}")
# 打印所有子目录(可选)
for dirname in dirnames:
dir_full_path = os.path.join(dirpath, dirname)
print(f"📁 子目录: {dir_full_path}")
# 调用函数
traverse_directory("/users/yourname/documents")
输出示例(简化)
🔍 正在遍历目录: /users/yourname/documents
📂 当前目录: /users/yourname/documents
📄 文件: /users/yourname/documents/report.pdf
📄 文件: /users/yourname/documents/config.json
📁 子目录: /users/yourname/documents/backup
📂 当前目录: /users/yourname/documents/backup
📄 文件: /users/yourname/documents/backup/old_data.zip
os.walk() 的内部机制:一个动态图解
让我们用 mermaid 画一张流程图,展示 os.walk() 如何递归遍历目录结构。

这个图展示了 os.walk() 的递归逻辑:先深入到底层,再逐步回溯处理每一层的文件。
处理常见异常:权限与路径错误
在真实环境中,你可能遇到以下问题:
- 目录不存在
- 无读取权限
- 文件名包含特殊字符(如中文、符号)
安全遍历:添加异常处理
import os
def safe_traverse(root_dir):
try:
if not os.path.exists(root_dir):
print("❌ 路径不存在!")
return
if not os.access(root_dir, os.r_ok):
print("❌ 没有读取权限!")
return
print(f"✅ 开始安全遍历: {root_dir}")
for dirpath, dirnames, filenames in os.walk(root_dir):
print(f"📂 目录: {dirpath}")
for filename in filenames:
file_path = os.path.join(dirpath, filename)
try:
# 尝试获取文件大小(测试是否可读)
size = os.path.getsize(file_path)
print(f"📄 {filename} (大小: {size} bytes)")
except oserror as e:
print(f"⚠️ 无法读取文件: {file_path} | 错误: {e}")
except exception as e:
print(f"💥 发生未知错误: {e}")
# 调用
safe_traverse("/users/yourname/documents")
关键点:
- 使用
os.path.exists()判断路径是否存在。 - 使用
os.access(path, os.r_ok)检查读权限。 - 在
os.walk()内部对每个文件加try-except,避免因单个文件失败导致整个遍历中断。
高级技巧:按条件筛选文件
很多时候我们不需要遍历所有文件,而是只关心特定类型的文件,比如 .py、.log、.jpg 等。
示例:只列出.txt和.md文件
import os
def filter_files_by_extension(root_dir, extensions):
matched_files = []
for dirpath, _, filenames in os.walk(root_dir):
for filename in filenames:
if any(filename.lower().endswith(ext.lower()) for ext in extensions):
full_path = os.path.join(dirpath, filename)
matched_files.append(full_path)
print(f"✅ 匹配: {full_path}")
print(f"\n📊 共找到 {len(matched_files)} 个匹配文件。")
return matched_files
# 使用
txt_md_files = filter_files_by_extension(
root_dir="/users/yourname/documents",
extensions=['.txt', '.md']
)
排除特定目录或文件
有时我们需要跳过某些目录,比如 .git、__pycache__、node_modules 等。
示例:排除隐藏目录和缓存目录
import os
def traverse_with_exclusions(root_dir, exclude_dirs=none):
if exclude_dirs is none:
exclude_dirs = {'.git', '__pycache__', 'node_modules', '.venv'}
print(f"🚀 开始遍历,排除: {exclude_dirs}")
for dirpath, dirnames, filenames in os.walk(root_dir):
# 动态过滤掉不想遍历的目录
dirnames[:] = [d for d in dirnames if d not in exclude_dirs]
print(f"📂 当前目录: {dirpath}")
for filename in filenames:
print(f"📄 {filename}")
# 调用
traverse_with_exclusions("/users/yourname/project")
dirnames[:] = [...] 是关键技巧——它修改了 os.walk() 的内部目录列表,实现“跳过”某些子目录。
获取文件详细信息:mtime、ctime、size
除了文件名,我们还常需要知道文件的创建时间、修改时间、大小等元数据。
示例:获取文件详细信息
import os
from datetime import datetime
def get_file_info(root_dir):
print("📊 文件详细信息汇总:")
print("-" * 60)
for dirpath, _, filenames in os.walk(root_dir):
for filename in filenames:
file_path = os.path.join(dirpath, filename)
try:
stat = os.stat(file_path)
# 转换时间戳为可读格式
mtime = datetime.fromtimestamp(stat.st_mtime).strftime('%y-%m-%d %h:%m:%s')
ctime = datetime.fromtimestamp(stat.st_ctime).strftime('%y-%m-%d %h:%m:%s')
size = stat.st_size
print(f"📄 {filename}")
print(f" 🕒 修改时间: {mtime}")
print(f" 🕒 创建时间: {ctime}")
print(f" 📏 大小: {size} bytes")
print(f" 📍 路径: {file_path}")
print("-" * 40)
except exception as e:
print(f"⚠️ 无法获取信息: {file_path} | 错误: {e}")
get_file_info("/users/yourname/documents")
说明:
os.stat()返回文件状态对象。st_mtime: 最后修改时间(modification time)st_ctime: 创建时间(creation time,部分系统支持)st_size: 文件大小(字节)
实战项目:批量重命名文件
假设你要将某个目录下所有的 .jpg 文件重命名为 img_001.jpg, img_002.jpg…
示例:自动重命名图片文件
import os
def rename_images_in_folder(folder_path, prefix="img"):
count = 1
renamed = 0
for dirpath, _, filenames in os.walk(folder_path):
for filename in filenames:
if filename.lower().endswith(('.jpg', '.jpeg', '.png', '.bmp')):
old_path = os.path.join(dirpath, filename)
new_filename = f"{prefix}_{count:03d}{os.path.splitext(filename)[1]}"
new_path = os.path.join(dirpath, new_filename)
try:
os.rename(old_path, new_path)
print(f"✅ 重命名: {filename} → {new_filename}")
renamed += 1
count += 1
except oserror as e:
print(f"❌ 重命名失败: {old_path} → {new_path} | 错误: {e}")
print(f"🎉 完成!共重命名 {renamed} 个文件。")
# 调用
rename_images_in_folder("/users/yourname/pictures")
这个脚本可以用于整理照片、清理命名混乱的文件夹。
使用 pathlib 替代 os?—— 一个现代建议
虽然 os 模块功能强大,但 python 3.4+ 推荐使用 pathlib 模块,它更面向对象,语法更清晰。
对比:os vs pathlib
1. 传统 os 写法:
import os
for dirpath, _, filenames in os.walk("/home/user/docs"):
for f in filenames:
path = os.path.join(dirpath, f)
if f.endswith(".log"):
print(path)
2. 现代 pathlib 写法:
from pathlib import path
root = path("/home/user/docs")
for file_path in root.rglob("*.log"):
print(file_path)
rglob() 是 glob() 的递归版本,相当于 os.walk() + glob 组合。
单元测试:确保你的遍历逻辑正确
为了保证代码健壮,我们可以写一个简单的测试用例。
import unittest
import os
import tempfile
class testdirectorytraversal(unittest.testcase):
def setup(self):
# 创建临时目录结构
self.temp_dir = tempfile.mkdtemp()
sub_dir = os.path.join(self.temp_dir, "subfolder")
os.makedirs(sub_dir)
with open(os.path.join(self.temp_dir, "test1.txt"), "w") as f:
f.write("hello")
with open(os.path.join(sub_dir, "test2.py"), "w") as f:
f.write("print('hi')")
def teardown(self):
# 清理临时目录
os.removedirs(self.temp_dir)
def test_traverse_with_filter(self):
from pathlib import path
matches = list(path(self.temp_dir).rglob("*.txt"))
self.assertequal(len(matches), 1)
self.assertin("test1.txt", str(matches[0]))
if __name__ == "__main__":
unittest.main()
性能对比:os.walk() vs pathlib.rglob()
| 方法 | 优点 | 缺点 |
|---|---|---|
os.walk() | 传统、兼容性好、灵活 | 代码略长,需手动拼接路径 |
pathlib.rglob() | 语法简洁,可读性强 | 需要 python 3.4+ |
推荐:新项目优先使用 pathlib,旧项目可保留 os.walk()。
实用技巧总结
| 技巧 | 说明 |
|---|---|
os.path.join() | 安全拼接路径,自动适配 os 分隔符 |
os.path.exists() | 检查路径是否存在 |
os.access() | 检查读写权限 |
os.stat() | 获取文件元数据 |
dirnames[:] = [...] | 动态跳过子目录 |
try-except 包裹文件操作 | 防止程序崩溃 |
pathlib.path().rglob() | 简洁的递归查找 |
结语:掌握 os.walk(),就是掌握自动化核心
遍历目录是几乎所有文件处理任务的基础。通过熟练运用 os 模块,尤其是 os.walk(),你可以构建出强大的自动化脚本,用于:
- 批量处理文件
- 日志分析
- 数据备份与迁移
- 安全扫描
- 自动化部署
记住:代码不是写出来的,是改出来的。多尝试不同的组合,多加异常处理,你的脚本才会真正“生产可用”。
今天的你,已经掌握了 python 中最实用的文件遍历技能!
现在就动手,打开你的终端,试试这段代码:
import os
for dirpath, dirnames, filenames in os.walk("/your/directory/path"):
for f in filenames:
print(f"📄 {os.path.join(dirpath, f)}")
以上就是python如何使用os模块遍历目录下的所有文件的详细内容,更多关于python os模块遍历文件的资料请关注代码网其它相关文章!
发表评论