接下来为你详细讲解 Python3 中 os 模块提供的文件和目录操作方法,同样从新手角度出发,结合大量例子,一步一步说清楚。
1. 先认识 os 模块
os 是 “Operating System”(操作系统)的缩写,它能让你在 Python 中执行和操作系统相关的各种命令,比如操作文件和文件夹、获取环境变量、执行系统命令等。
我们这里只聚焦在文件和目录相关的方法。
要使用它,第一步永远是:
2. 当前工作目录操作
程序运行时有一个“当前工作目录”(Current Working Directory),很多相对路径操作都基于它。
2.1 os.getcwd() — 查看当前在哪里
import oscurrent = os.getcwd()print(current) # 比如输出:/Users/yourname/projects
getcwd 全称:get current working directory。
它返回一个字符串,表示程序目前所在的文件夹路径。
2.2 os.chdir(path) — 换个目录
os.chdir('/Users/yourname/Desktop') # 切换到桌面print(os.getcwd()) # 确认一下
chdir 全称:change directory。
path 可以是一个相对路径,比如 os.chdir('..') 表示回到上一级目录。
如果目录不存在,会抛出 FileNotFoundError。
3. 查看目录里有什么:os.listdir()
items = os.listdir('.') # 当前目录print(items)# 输出:['file1.txt', 'folderA', 'image.png', ...]
listdir(path) 返回一个列表,包含该目录下所有文件和子目录的名称(只有名字,不含完整路径)。
如果不传参数,默认列出当前工作目录。
注意事项:
- 返回的名字只是字符串,要判断它是文件还是文件夹,需要配合
os.path(后面会讲)。 - 如果目录不存在,报
FileNotFoundError。
4. 创建目录
4.1 os.mkdir(path) — 创建一个文件夹
os.mkdir('新文件夹') # 在当前目录下创建一个名为“新文件夹”的目录
- 如果文件夹已存在,会报
FileExistsError。
# 错误示例:中间目录不存在os.mkdir('a/b/c') # 如果 a 或 a/b 不存在,就会报错 FileNotFoundError
4.2 os.makedirs(path) — 一口气创建多层目录
os.makedirs('a/b/c') # 即使 a、a/b 不存在,也会一并创建
这个函数相当于在命令行里执行 mkdir -p,非常方便。
参数 exist_ok=True(Python 3.2+):
如果目录已经存在,默认会报错。加上 exist_ok=True 后,已存在也不会报错。
os.makedirs('a/b/c', exist_ok=True) # 安全创建,存在也不会崩
5. 删除目录
5.1 os.rmdir(path) — 删除一个空目录
os.rmdir('空文件夹') # 只能删除空目录
- 如果目录不为空(里面有文件或其他文件夹),会抛
OSError。 - 如果目录不存在,抛
FileNotFoundError。
5.2 os.removedirs(path) — 递归删除空目录
它会试图从最末级目录开始向上删除,直到遇到非空目录为止。
# 假设 a/b/c 三个目录都是空的os.removedirs('a/b/c') # 会依次删除 c、b、a,如果其中某个变非空就停
注意: 这个函数有风险,因为它会“向上”一路删空目录,可能不小心删掉需要的父目录。新手建议谨慎使用,或者明确用 shutil.rmtree() 删除非空目录(不是 os 里的)。
6. 删除文件:os.remove(path)
os.remove('old_file.txt') # 彻底删除文件(不进回收站)
- 文件不存在会报
FileNotFoundError。 - 删除不可恢复,操作前一定要确认!
7. 重命名文件或目录:os.rename(src, dst)
# 重命名文件os.rename('旧名.txt', '新名.txt')# 重命名文件夹os.rename('旧文件夹', '新文件夹')
- 如果目标路径(dst)已经存在,在 Windows 上会报错;在 Unix 上可能会覆盖(静默替换)。
os.rename('file.txt', '../backup/file.txt') # 把文件移到上级的 backup 目录下
- 跨文件系统的移动可能失败,此时可以用
shutil.move()。
还有一个 os.replace(src, dst):用法相同,但跨平台行为更一致——如果目标存在,会直接替换掉。更安全可靠。
8. 获取文件/目录信息:os.stat(path)
info = os.stat('example.txt')print(info)# os.stat_result(st_mode=33188, st_ino=12345, st_dev=..., st_size=1024, ...)
返回一个类似元组的对象,包含文件的各种属性,常用的有:
st_sizest_mtimest_ctime:创建时间(Windows)或最后元数据变更时间(Unix)st_mode
可以用 stat 模块解析 st_mode,但新手记住下面这些就行:
import timefile_size = info.st_size # 文件大小mod_time = time.ctime(info.st_mtime) # 人类可读的修改时间print(f'大小:{file_size} 字节,修改时间:{mod_time}')
如果文件不存在,报 FileNotFoundError。
9. 遍历目录树:强大的文件查找工具
9.1 os.walk(top) — 递归遍历所有子目录和文件
这是处理批量文件时最常用的方法。它会自顶向下(或自底向上)遍历一棵目录树。
for dirpath, dirnames, filenames in os.walk('.'): print(f'当前目录: {dirpath}') print(f' 子文件夹: {dirnames}') print(f' 文件: {filenames}')
os.walk 每次循环返回三个值:
实例:找出某个文件夹下所有 .txt 文件
target_dir = 'documents'for root, dirs, files in os.walk(target_dir): for file in files: if file.endswith('.txt'): full_path = os.path.join(root, file) print(full_path)
注意:如果想修改遍历行为(比如跳过某些文件夹),可以修改 dirnames 列表(例如删除某个名字),walk 就不会进入那个目录。
for root, dirs, files in os.walk('.'): if '.git' in dirs: dirs.remove('.git') # 不遍历 .git 文件夹 # ... 其他操作
9.2 os.scandir(path) — 更高效地列出目录(Python 3.5+)
scandir 返回一个迭代器,每个条目是 DirEntry 对象,查询属性时不需要额外的系统调用,比 os.listdir 加 os.stat 快很多。
with os.scandir('.') as entries: for entry in entries: if entry.is_file(): print(f'文件: {entry.name}, 大小: {entry.stat().st_size}') elif entry.is_dir(): print(f'目录: {entry.name}')
entry.nameentry.pathentry.is_file()entry.stat()
推荐在需要遍历目录并检查类型时使用。
10. os.path 模块:路径操作的瑞士军刀
os.path 是 os 里面的一个子模块,专门用来操作文件路径字符串(拼接、拆分、判断存在等)。它不访问实际文件,只是处理字符串,但配合前面的方法威力巨大。
通常这样用:
import os.path# 或者直接 import os,然后用 os.path.xxx
10.1 拼接路径:os.path.join()
最重要的路径函数,没有之一! 不要手动用 + 或 \ 拼接路径,因为它会自动处理不同操作系统的分隔符。
folder = 'data'filename = 'result.txt'full_path = os.path.join(folder, filename)print(full_path) # Windows 下: data\result.txt Linux/Mac 下: data/result.txt
可以拼接多个部分:
path = os.path.join('home', 'user', 'docs', 'file.txt')
10.2 判断是否存在:os.path.exists(path)
if os.path.exists('data.txt'): print('文件或文件夹存在')else: print('不存在')
10.3 判断是文件还是文件夹
if os.path.isfile('data.txt'): print('这是一个文件')elif os.path.isdir('data.txt'): print('这是一个目录')
10.4 获取绝对路径
print(os.path.abspath('.')) # 当前目录的绝对路径
10.5 拆分路径
dir_part, file_part = os.path.split('/home/user/file.txt')# dir_part = '/home/user', file_part = 'file.txt'
name, ext = os.path.splitext('archive.tar.gz')# name = 'archive.tar', ext = '.gz' (只认最后一个点)
os.path.dirname(path)os.path.basename(path)
10.6 获取文件大小
os.path.getsize(path) 返回字节数。
size = os.path.getsize('picture.jpg')print(f'文件大小: {size} 字节')
如果文件不存在,报错。
10.7 获取文件时间
os.path.getmtime(path)os.path.getctime(path):创建时间(Windows)或元数据变更时间(Unix)os.path.getatime(path)
返回时间戳,配合 time.ctime() 可读。
11. 新手必看的常见错误与安全写法
11.1 操作前先检查是否存在
if os.path.exists('folder'): os.rmdir('folder')else: print('目录不存在')
11.2 创建目录用 exist_ok=True
os.makedirs('a/b/c', exist_ok=True) # 不会因为已存在而报错
11.3 捕获异常
很多操作可能会因为权限不足、路径不存在等原因失败,用 try...except 更稳健。
try: os.remove('temp_file.txt')except FileNotFoundError: print('文件本来就不存在')except PermissionError: print('没有权限删除')
11.4 使用 os.path.join 避免硬编码斜杠
永远不要写 'folder\\file',用 os.path.join('folder', 'file')。
11.5 遍历大目录时,推荐 os.scandir() 或 os.walk()
os.listdir() 一次返回所有名字,如果目录里文件很多会占很多内存。而 scandir 是迭代器,节省内存。
12. 更现代的替代:pathlib
Python 3.4 引入了 pathlib 模块,用面向对象的方式操作路径,很多操作比 os.path 更直观。例如:
from pathlib import Pathp = Path('data') / 'file.txt'print(p.exists())print(p.is_file())p.mkdir(parents=True, exist_ok=True) # 等同于 os.makedirs
但 os 模块仍然被广泛使用,尤其是老项目中。掌握 os 和 os.path 是基本功,pathlib 可作为进阶补充。
13. 总结:常用方法速查表
分类 | 方法 | 用途 |
工作目录 | os.getcwd()
| 获取当前目录 |
| os.chdir(path)
| 切换当前目录 |
列表 | os.listdir(path)
| 列出目录内容(名称列表) |
| os.scandir(path)
| 高效列出目录,返回 DirEntry 迭代器 |
创建 | os.mkdir(path)
| 创建单层目录 |
| os.makedirs(path, exist_ok=False)
| 创建多层目录 |
删除 | os.rmdir(path)
| 删除空目录 |
| os.removedirs(path)
| 递归删空目录 |
| os.remove(path)
| 删除文件 |
重命名/移动 | os.rename(src, dst)
| 重命名或移动 |
| os.replace(src, dst)
| 更安全的重命名(会覆盖) |
信息 | os.stat(path)
| 获取文件/目录详细信息 |
遍历 | os.walk(top)
| 递归遍历目录树 |
路径操作 | os.path.join()
| 智能拼接路径 |
| os.path.exists()
| 是否存在 |
| os.path.isfile() / isdir()
| 是文件/目录? |
| os.path.split() / splitext()
| 拆分路径/扩展名 |
| os.path.abspath()
| 获取绝对路径 |
| os.path.getsize()
| 文件大小(字节) |
| os.path.getmtime() / getctime()
| 获取时间 |