文件与目录操作
本教程共 70 篇 · 第 45 篇 · 更新于 2026-07-22 · 约 5 分钟阅读
45. 文件与目录操作
本节目标:学会用
os和shutil操作文件系统,掌握pathlib的现代路径处理方式。
44 章讲的是「读写文件内容」。日常开发中,你还需要创建目录、移动文件、删除文件、遍历文件夹。这些操作由 os、shutil 和 pathlib 三个模块负责。
os 模块:与操作系统打交道
os 模块提供了大量与操作系统交互的函数。文件系统相关的是 os.path 子模块。
路径操作
import os
# 获取当前工作目录
print(os.getcwd())
# 切换目录
os.chdir('/tmp')
# 列出目录内容
print(os.listdir('.'))
# 创建目录
os.mkdir('new_folder') # 创建单层目录
os.makedirs('a/b/c', exist_ok=True) # 递归创建,已存在不报错
# 删除目录
os.rmdir('new_folder') # 删除空目录
os.removedirs('a/b/c') # 递归删除空目录
# 删除文件
os.remove('old.txt')
os.unlink('old.txt') # 同 remove
# 重命名
os.rename('old.txt', 'new.txt')
Warning
os.remove()和os.rmdir()删除的东西不会进回收站,是直接抹掉。删除前务必确认路径正确,尤其是写批量删除脚本时。
os.path:路径处理工具
import os.path
# 拼接路径(自动处理不同系统的分隔符)
path = os.path.join('data', '2024', 'report.txt')
# Windows: data\2024\report.txt
# Linux/macOS: data/2024/report.txt
# 拆分路径
print(os.path.split(path)) # ('data/2024', 'report.txt')
print(os.path.splitext(path)) # ('data/2024/report', '.txt')
# 获取绝对路径
print(os.path.abspath('report.txt'))
# 判断类型
print(os.path.exists(path)) # 是否存在
print(os.path.isfile(path)) # 是否是文件
print(os.path.isdir(path)) # 是否是目录
# 获取文件大小和修改时间
print(os.path.getsize('report.txt'))
print(os.path.getmtime('report.txt')) # 返回时间戳
os.path.join 是跨平台的关键。Windows 用反斜杠 \,Linux/macOS 用正斜杠 /。手动拼接路径字符串,代码到了别的系统就会出错。
shutil:高级文件操作
shutil 提供了 os 没有的「拷贝」「移动」「压缩」等功能:
import shutil
# 复制文件
shutil.copy('src.txt', 'dst.txt') # 复制内容和权限
shutil.copy2('src.txt', 'dst.txt') # 额外保留元数据(修改时间等)
# 复制目录树
shutil.copytree('source_dir', 'backup_dir')
# 移动文件或目录
shutil.move('old_name.txt', 'new_name.txt')
# 删除目录树(不管是否为空)
shutil.rmtree('temp_dir')
# 压缩
shutil.make_archive('backup', 'zip', 'source_dir')
# 生成 backup.zip
Note
shutil.copytree()在目标目录已存在时会报错。Python 3.8+ 可以加dirs_exist_ok=True参数覆盖。
pathlib:面向对象的路径处理(推荐)
os.path 的函数式接口在简单场景下够用,但路径一多,代码会变得冗长。Python 3.4 引入的 pathlib 用面向对象的方式处理路径,更现代、更易读:
from pathlib import Path
# 创建路径对象
p = Path('data') / '2024' / 'report.txt'
print(p) # data/2024/report.txt(自动处理分隔符)
# 路径属性
print(p.name) # report.txt
print(p.stem) # report
print(p.suffix) # .txt
print(p.parent) # data/2024
print(p.parts) # ('data', '2024', 'report.txt')
# 判断与遍历
print(p.exists())
print(p.is_file())
print(p.is_dir())
# 遍历目录
for file in Path('data').iterdir():
print(file)
# glob 匹配
for pyfile in Path('.').glob('*.py'):
print(pyfile)
# 递归匹配
for txt in Path('.').rglob('*.txt'):
print(txt)
Tip
Path对象支持/运算符拼接路径,比os.path.join更直观。而且它本身就是路径,不用在字符串和路径函数之间来回转换。
pathlib 的读写方法
Path 对象还封装了文件读写,不需要手动 open():
p = Path('note.txt')
# 读文本
content = p.read_text(encoding='utf-8')
# 写文本
p.write_text('新内容', encoding='utf-8')
# 读二进制
binary_data = p.read_bytes()
# 写二进制
p.write_bytes(b'\x89PNG')
这些方法内部自动处理 with 和资源关闭,写小文件时非常省事。
Warning
write_text()会覆盖原文件内容。如果你想追加,还是得用open()的'a'模式。pathlib没有提供追加的便捷方法。
实战:批量重命名照片
假设你有一堆照片,想按日期重命名:
from pathlib import Path
import shutil
from datetime import datetime
src_dir = Path('photos')
dst_dir = Path('organized')
dst_dir.mkdir(exist_ok=True)
for photo in src_dir.glob('*.jpg'):
mtime = datetime.fromtimestamp(photo.stat().st_mtime)
new_name = mtime.strftime('%Y%m%d_%H%M%S') + photo.suffix
shutil.copy2(photo, dst_dir / new_name)
print(f"{photo.name} -> {new_name}")
这段代码展示了 pathlib、shutil 和 os.stat 的结合。photo.stat() 返回文件元数据,.st_mtime 是最后修改时间戳。
os vs pathlib:怎么选
| 场景 | 推荐 |
|---|---|
| 简单路径拼接 | pathlib.Path |
| 需要环境变量或系统调用 | os |
| 复制/移动/删除目录树 | shutil |
| 遍历和过滤文件 | pathlib.Path.glob / rglob |
| 维护兼容 Python 2 的代码 | os.path(别无选择) |
新项目优先用 pathlib,代码更清晰。遇到 pathlib 没有的功能(比如 shutil.copytree),再回头找 os 和 shutil。
小结
os提供底层文件系统操作,os.path处理路径字符串。shutil负责复制、移动、删除目录树等高级操作。pathlib用面向对象方式处理路径,是现代 Python 的首选。- 批量操作文件前,先在测试目录里跑一遍,确认逻辑正确再动真实数据。
文件系统操作有「破坏性」——删了就是删了,很难恢复。写脚本时保持谨慎,多用 print 预览操作结果,确认无误再执行真正的删除或覆盖。
来源:参考了 runoob「Python3 OS 文件/目录方法」、liaoxuefeng「操作文件和目录」、pythondoc「11. 文件和目录访问」等,改写后所得。