1. 引言
在日常的 Python 开发中,我们经常需要遍历目录、查看目录下的文件列表,或者递归地处理某个文件夹下的所有内容。无论是做文件管理工具、批量处理脚本,还是构建自动化流程,列出目录都是一项基础且高频的操作。
2. 准备工作
在开始之前,请确保你的环境中已经安装了 Python3(建议 3.6 及以上版本)。本文所有示例均使用 Python 标准库,无需安装任何第三方依赖。
你可以通过以下命令检查 Python 版本:
python3--version本文的示例代码将围绕一个示例目录结构展开,假设目录如下:
sample_dir/ ├── file1.txt ├── file2.py ├── sub_dir/ │ ├── inner_file.md │ └── another_dir/ │ └── deep_file.log └── notes/ └── readme.txt3. 使用 os.listdir() 列出目录
os.listdir()是 Python 中最基础、最直接的列出目录方法。它接收一个路径字符串作为参数,返回该目录下所有条目(文件和子目录)的名称列表。
3.1 基本用法
importos path="sample_dir"entries=os.listdir(path)print(entries)输出结果:
['file1.txt', 'file2.py', 'sub_dir', 'notes']3.2 过滤出文件或目录
os.listdir()返回的结果不区分文件和目录,我们可以结合os.path.isdir()或os.path.isfile()进行过滤:
importos path="sample_dir"entries=os.listdir(path)files=[eforeinentriesifos.path.isfile(os.path.join(path,e))]dirs=[eforeinentriesifos.path.isdir(os.path.join(path,e))]print("文件:",files)print("目录:",dirs)输出结果:
文件: ['file1.txt', 'file2.py'] 目录: ['sub_dir', 'notes']3.3 优缺点
- 优点:简单直接,性能好,适合快速获取单层目录内容。
- 缺点:只返回名称,不包含文件大小、修改时间等元数据;不递归子目录。
4. 使用 os.scandir() 高效遍历
os.scandir()是 Python 3.5 引入的改进版目录遍历方法。它返回一个迭代器,每个元素是一个DirEntry对象,包含文件名以及文件类型等元数据,避免了额外的系统调用,性能优于os.listdir()+os.path.isdir()的组合。
4.1 基本用法
importos path="sample_dir"withos.scandir(path)asentries:forentryinentries:print(entry.name)输出结果:
file1.txt file2.py sub_dir notes4.2 判断文件类型
DirEntry对象提供了is_file()和is_dir()方法,可以直接判断类型:
importos path="sample_dir"withos.scandir(path)asentries:forentryinentries:ifentry.is_file():print(f"[文件]{entry.name}")elifentry.is_dir():print(f"[目录]{entry.name}")输出结果:
[文件] file1.txt [文件] file2.py [目录] sub_dir [目录] notes4.3 优缺点
- 优点:性能高,能直接获取文件类型和部分元数据,推荐在需要遍历大量文件时使用。
- 缺点:返回的是迭代器,需要配合
with语句使用以释放资源。
5. 使用 pathlib.Path.iterdir() 面向对象遍历
pathlib是 Python 3.4 引入的面向对象文件路径库,Path.iterdir()返回一个生成器,逐个产出该目录下的Path对象。它让代码更简洁、可读性更高,是 Python3 官方推荐的路径处理方式。
5.1 基本用法
frompathlibimportPath path=Path("sample_dir")forchildinpath.iterdir():print(child.name)输出结果:
file1.txt file2.py sub_dir notes5.2 过滤文件与目录
Path对象自带is_file()和is_dir()方法,配合列表推导式可以优雅地过滤:
frompathlibimportPath path=Path("sample_dir")files=[p.nameforpinpath.iterdir()ifp.is_file()]dirs=[p.nameforpinpath.iterdir()ifp.is_dir()]print("文件:",files)print("目录:",dirs)输出结果:
文件: ['file1.txt', 'file2.py'] 目录: ['sub_dir', 'notes']5.3 优缺点
- 优点:代码简洁、面向对象、跨平台性好,是 Python3 的推荐写法。
- 缺点:相比
os.scandir()略慢,但在绝大多数场景下性能差异可忽略。
6. 使用 os.walk() 递归遍历目录树
os.walk()用于递归遍历目录树,它会自上而下(或自下而上)地生成一个三元组(dirpath, dirnames, filenames),分别表示当前目录路径、子目录列表、文件列表。这是处理嵌套目录结构时最常用的方法。
6.1 基本用法
importos root="sample_dir"fordirpath,dirnames,filenamesinos.walk(root):print(f"当前目录:{dirpath}")print(f" 子目录:{dirnames}")print(f" 文件:{filenames}")输出结果:
当前目录:sample_dir 子目录:['sub_dir', 'notes'] 文件:['file1.txt', 'file2.py'] 当前目录:sample_dir/sub_dir 子目录:['another_dir'] 文件:['inner_file.md'] 当前目录:sample_dir/sub_dir/another_dir 子目录:[] 文件:['deep_file.log'] 当前目录:sample_dir/notes 子目录:[] 文件:['readme.txt']6.2 收集所有文件路径
我们可以利用os.walk()递归收集所有文件的完整路径:
importos root="sample_dir"all_files=[]fordirpath,_,filenamesinos.walk(root):forfilenameinfilenames:all_files.append(os.path.join(dirpath,filename))forfinall_files:print(f)输出结果:
sample_dir/file1.txt sample_dir/file2.py sample_dir/sub_dir/inner_file.md sample_dir/sub_dir/another_dir/deep_file.log sample_dir/notes/readme.txt6.3 优缺点
- 优点:功能强大,支持递归遍历,可灵活控制遍历顺序和剪枝。
- 缺点:代码相对繁琐,需要手动拼接路径。
7. 使用 pathlib.Path.rglob() 递归匹配
Path.rglob()是pathlib提供的递归通配符匹配方法,可以按模式匹配目录树中的所有文件。它非常适合「查找特定类型文件」的场景。
7.1 基本用法
frompathlibimportPath root=Path("sample_dir")forpinroot.rglob("*"):print(p)输出结果:
sample_dir/file1.txt sample_dir/file2.py sample_dir/sub_dir sample_dir/sub_dir/inner_file.md sample_dir/sub_dir/another_dir sample_dir/sub_dir/another_dir/deep_file.log sample_dir/notes sample_dir/notes/readme.txt7.2 按扩展名匹配文件
frompathlibimportPath root=Path("sample_dir")forpinroot.rglob("*.txt"):print(p)输出结果:
sample_dir/file1.txt sample_dir/notes/readme.txt7.3 优缺点
- 优点:语法简洁,支持通配符模式匹配,适合查找特定文件。
- 缺点:只返回匹配项,不提供目录遍历的完整控制。
8. 方法对比与选择建议
下表总结了上述几种方法的适用场景:
| 方法 | 是否递归 | 返回内容 | 推荐场景 |
|---|---|---|---|
os.listdir() | 否 | 名称列表 | 快速获取单层目录内容 |
os.scandir() | 否 | DirEntry对象 | 大量文件遍历,需要文件类型 |
pathlib.Path.iterdir() | 否 | Path对象 | 面向对象写法,单层遍历 |
os.walk() | 是 | 目录树三元组 | 递归处理整个目录树 |
pathlib.Path.rglob() | 是 | Path对象 | 按模式递归查找文件 |
选择建议:
- 只需要单层文件名列表 →
os.listdir()。 - 需要高性能遍历且关心文件类型 →
os.scandir()。 - 追求代码简洁、面向对象 →
pathlib.Path.iterdir()。 - 需要递归处理所有子目录 →
os.walk()。 - 需要按通配符递归查找 →
pathlib.Path.rglob()。
9. 总结
本文详细介绍了 Python3 中列出目录的 5 种常用方法,从基础的os.listdir()到高效的os.scandir(),再到面向对象的pathlib系列,以及递归遍历的os.walk()和rglob()。每种方法都有其独特的适用场景,你可以根据实际需求灵活选择。
在实际开发中,推荐优先使用pathlib模块,它更符合 Python3 的现代编程风格,代码也更易读、易维护。希望本文能帮助你更好地掌握 Python 目录操作,提升开发效率。