ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Python进阶 - os模块 遍历目录下的所有文件

Python进阶 - os模块 遍历目录下的所有文件

👋 大家好,欢迎来到我的技术博客!
📚 在这里,我会分享学习笔记、实战经验与技术思考,力求用简单的方式讲清楚复杂的问题。
🎯 本文将围绕Python进阶这个话题展开,希望能为你带来一些启发或实用的参考。
🌱 无论你是刚入门的新手,还是正在进阶的开发者,希望你都能有所收获!


文章目录

  • 🐍 Python进阶:os模块遍历目录下的所有文件 🌳
    • 📁 什么是 os 模块?
    • 🚶‍♂️ 基础:使用 os.listdir() 遍历目录
    • 🔍 递归遍历:os.walk() —— 真正的“全遍历”工具
      • ✅ 示例代码:完整递归遍历
      • 🧩 输出示例(简化):
    • 🌐 os.walk() 的内部机制:一个动态图解
    • ⚠️ 处理常见异常:权限与路径错误
      • ✅ 安全遍历:添加异常处理
    • 🔎 高级技巧:按条件筛选文件
      • ✅ 示例:只列出 `.txt` 和 `.md` 文件
    • 🗂️ 排除特定目录或文件
      • ✅ 示例:排除隐藏目录和缓存目录
    • 🕵️‍♀️ 获取文件详细信息:mtime、ctime、size
      • ✅ 示例:获取文件详细信息
    • 🔄 实战项目:批量重命名文件
      • ✅ 示例:自动重命名图片文件
    • 🛠️ 使用 pathlib 替代 os?—— 一个现代建议
      • ✅ 对比:os vs pathlib
        • 1. 传统 os 写法:
        • 2. 现代 pathlib 写法:
    • 🧪 单元测试:确保你的遍历逻辑正确
    • 📊 性能对比:os.walk() vs pathlib.rglob()
    • 🧩 实用技巧总结
    • 🌐 附加资源 & 学习建议
    • 🎯 结语:掌握 os.walk(),就是掌握自动化核心

🐍 Python进阶:os模块遍历目录下的所有文件 🌳

在日常的编程工作中,我们经常需要处理文件和目录的操作。无论是数据清洗、日志分析、批量重命名,还是自动化脚本编写,遍历目录中的所有文件都是一个非常基础但又极其重要的技能。而os模块作为 Python 标准库中与操作系统交互的核心模块,提供了强大的功能来完成这项任务。

今天,我们就来深入探讨如何使用os模块高效、安全地遍历目录下的所有文件,包括子目录、隐藏文件、权限控制等高级场景,并通过实际代码示例带你从入门到精通。✨


📁 什么是 os 模块?

os模块是 Python 的标准库之一,它提供了一种方式来使用操作系统的功能,如文件和目录操作、环境变量管理、进程管理等。它在不同平台上(Windows、Linux、macOS)都能保持一致的行为,是跨平台开发的理想选择。

💡 提示:os模块不依赖外部库,开箱即用,非常适合做系统级操作。


🚶‍♂️ 基础:使用 os.listdir() 遍历目录

最简单的遍历方式是使用os.listdir()函数。它返回指定目录下所有文件和子目录的名称列表。

importos# 指定要遍历的目录路径directory="/path/to/your/folder"# 获取目录内容files_and_dirs=os.listdir(directory)print("目录内容:")foriteminfiles_and_dirs:print(f"📁{item}")

📌注意

  • os.listdir()只列出当前目录的内容,不会递归进入子目录。
  • 它返回的是字符串列表,包含文件名和文件夹名。
  • 如果路径不存在或没有访问权限,会抛出FileNotFoundErrorPermissionError

🔍 递归遍历:os.walk() —— 真正的“全遍历”工具

如果你需要遍历一个目录及其所有子目录中的文件,os.walk()是你的首选。它是一个生成器函数,逐层返回(dirpath, dirnames, filenames)三元组。

✅ 示例代码:完整递归遍历

importosdeftraverse_directory(root_dir):print(f"🔍 正在遍历目录:{root_dir}")fordirpath,dirnames,filenamesinos.walk(root_dir):# 打印当前目录路径print(f"📂 当前目录:{dirpath}")# 打印所有文件forfilenameinfilenames:file_path=os.path.join(dirpath,filename)print(f"📄 文件:{file_path}")# 打印所有子目录(可选)fordirnameindirnames: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()的递归逻辑:先深入到底层,再逐步回溯处理每一层的文件


⚠️ 处理常见异常:权限与路径错误

在真实环境中,你可能遇到以下问题:

  • 目录不存在
  • 无读取权限
  • 文件名包含特殊字符(如中文、符号)

✅ 安全遍历:添加异常处理

importosdefsafe_traverse(root_dir):try:ifnotos.path.exists(root_dir):print("❌ 路径不存在!")returnifnotos.access(root_dir,os.R_OK):print("❌ 没有读取权限!")returnprint(f"✅ 开始安全遍历:{root_dir}")fordirpath,dirnames,filenamesinos.walk(root_dir):print(f"📂 目录:{dirpath}")forfilenameinfilenames:file_path=os.path.join(dirpath,filename)try:# 尝试获取文件大小(测试是否可读)size=os.path.getsize(file_path)print(f"📄{filename}(大小:{size}bytes)")exceptOSErrorase:print(f"⚠️ 无法读取文件:{file_path}| 错误:{e}")exceptExceptionase: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文件

importosdeffilter_files_by_extension(root_dir,extensions):matched_files=[]fordirpath,_,filenamesinos.walk(root_dir):forfilenameinfilenames:ifany(filename.lower().endswith(ext.lower())forextinextensions):full_path=os.path.join(dirpath,filename)matched_files.append(full_path)print(f"✅ 匹配:{full_path}")print(f"\n📊 共找到{len(matched_files)}个匹配文件。")returnmatched_files# 使用txt_md_files=filter_files_by_extension(root_dir="/Users/yourname/Documents",extensions=['.txt','.md'])

🗂️ 排除特定目录或文件

有时我们需要跳过某些目录,比如.git__pycache__node_modules等。

✅ 示例:排除隐藏目录和缓存目录

importosdeftraverse_with_exclusions(root_dir,exclude_dirs=None):ifexclude_dirsisNone:exclude_dirs={'.git','__pycache__','node_modules','.venv'}print(f"🚀 开始遍历,排除:{exclude_dirs}")fordirpath,dirnames,filenamesinos.walk(root_dir):# 动态过滤掉不想遍历的目录dirnames[:]=[dfordindirnamesifdnotinexclude_dirs]print(f"📂 当前目录:{dirpath}")forfilenameinfilenames:print(f"📄{filename}")# 调用traverse_with_exclusions("/Users/yourname/project")

dirnames[:] = [...]是关键技巧——它修改了os.walk()的内部目录列表,实现“跳过”某些子目录。


🕵️‍♀️ 获取文件详细信息:mtime、ctime、size

除了文件名,我们还常需要知道文件的创建时间、修改时间、大小等元数据。

✅ 示例:获取文件详细信息

importosfromdatetimeimportdatetimedefget_file_info(root_dir):print("📊 文件详细信息汇总:")print("-"*60)fordirpath,_,filenamesinos.walk(root_dir):forfilenameinfilenames: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_sizeprint(f"📄{filename}")print(f" 🕒 修改时间:{mtime}")print(f" 🕒 创建时间:{ctime}")print(f" 📏 大小:{size}bytes")print(f" 📍 路径:{file_path}")print("-"*40)exceptExceptionase: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

✅ 示例:自动重命名图片文件

importosdefrename_images_in_folder(folder_path,prefix="img"):count=1renamed=0fordirpath,_,filenamesinos.walk(folder_path):forfilenameinfilenames:iffilename.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+=1count+=1exceptOSErrorase: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 写法:
importosfordirpath,_,filenamesinos.walk("/home/user/docs"):forfinfilenames:path=os.path.join(dirpath,f)iff.endswith(".log"):print(path)
2. 现代 pathlib 写法:
frompathlibimportPath root=Path("/home/user/docs")forfile_pathinroot.rglob("*.log"):print(file_path)

🌟rglob()glob()的递归版本,相当于os.walk()+glob组合。

🔗 Python 官方文档 - pathlib
🔗 Real Python - pathlib 教程


🧪 单元测试:确保你的遍历逻辑正确

为了保证代码健壮,我们可以写一个简单的测试用例。

importunittestimportosimporttempfileclassTestDirectoryTraversal(unittest.TestCase):defsetUp(self):# 创建临时目录结构self.temp_dir=tempfile.mkdtemp()sub_dir=os.path.join(self.temp_dir,"subfolder")os.makedirs(sub_dir)withopen(os.path.join(self.temp_dir,"test1.txt"),"w")asf:f.write("hello")withopen(os.path.join(sub_dir,"test2.py"),"w")asf:f.write("print('hi')")deftearDown(self):# 清理临时目录os.removedirs(self.temp_dir)deftest_traverse_with_filter(self):frompathlibimportPath 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()简洁的递归查找

🌐 附加资源 & 学习建议

  • 📘 Python 官方文档 - os 模块
  • 📘 Python 官方文档 - pathlib
  • 📘 GeeksforGeeks - Python os.walk()
  • 📘 Real Python - Working with Files and Directories

🎯 结语:掌握 os.walk(),就是掌握自动化核心

遍历目录是几乎所有文件处理任务的基础。通过熟练运用os模块,尤其是os.walk(),你可以构建出强大的自动化脚本,用于:

  • 批量处理文件
  • 日志分析
  • 数据备份与迁移
  • 安全扫描
  • 自动化部署

🧠 记住:代码不是写出来的,是改出来的。多尝试不同的组合,多加异常处理,你的脚本才会真正“生产可用”。

🌟 今天的你,已经掌握了 Python 中最实用的文件遍历技能!


🐍现在就动手,打开你的终端,试试这段代码:

importosfordirpath,dirnames,filenamesinos.walk("/your/directory/path"):forfinfilenames:print(f"📄{os.path.join(dirpath,f)}")

你会发现,原来文件管理也可以如此简单、优雅、高效!💪


愿你在 Python 的世界里,像os.walk()一样,不断深入,永不终止。


🙌 感谢你读到这里!
🔍 技术之路没有捷径,但每一次阅读、思考和实践,都在悄悄拉近你与目标的距离。
💡 如果本文对你有帮助,不妨 👍点赞、📌收藏、📤分享给更多需要的朋友!
💬 欢迎在评论区留下你的想法、疑问或建议,我会一一回复,我们一起交流、共同成长 🌿
🔔 关注我,不错过下一篇干货!我们下期再见!✨

返回列表