python

关注公众号 jb51net

关闭
首页 > 脚本专栏 > python > Python os模块遍历文件

Python如何使用os模块遍历目录下的所有文件

作者:知远漫谈

在日常的编程工作中,我们经常需要处理文件和目录的操作,今天,我们就来深入探讨如何使用 os 模块高效、安全地遍历目录下的所有文件,包括子目录、隐藏文件、权限控制等高级场景

在日常的编程工作中,我们经常需要处理文件和目录的操作。无论是数据清洗、日志分析、批量重命名,还是自动化脚本编写,遍历目录中的所有文件都是一个非常基础但又极其重要的技能。而 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.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")

关键点:

高级技巧:按条件筛选文件

很多时候我们不需要遍历所有文件,而是只关心特定类型的文件,比如 .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")

说明:

实战项目:批量重命名文件

假设你要将某个目录下所有的 .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模块遍历文件的资料请关注脚本之家其它相关文章!

您可能感兴趣的文章:
阅读全文