Python 操作文件和目录:程序的"文件管理器"
引言:从"手动整理"到"自动管家"
想象你管理一个仓库:
- 手动整理:自己搬箱子、贴标签、找位置——累,且容易记错;
- 自动管家(
os模块):告诉管家"把 A 箱子搬到 B 区"、"列出所有红色箱子"——管家自动完成,你只看结果。
Python 的 os 模块就是程序的"文件管家"——创建目录、移动文件、查找筛选,一句话搞定。
一、os 模块:操作系统的"遥控器"
1.1 判断操作系统类型
import os
print(os.name) # 'posix' = Linux/Unix/macOS,'nt' = Windows注意:os 模块的某些函数跟操作系统相关——比如 os.uname() 在 Windows 上没有。
1.2 环境变量
# 查看所有环境变量
print(os.environ)
# 获取某个环境变量
path = os.environ.get('PATH')
print(path)
# 带默认值
home = os.environ.get('HOME', '/default/home')生活化理解:环境变量是"仓库的规章制度"——PATH 是"常用工具存放区",HOME 是"管理员办公室"。
二、目录操作:创建、删除、查看
2.1 核心函数
| 函数 | 作用 | 类比 |
|---|---|---|
os.path.abspath('.') | 当前目录绝对路径 | 你现在站在哪 |
os.path.join(a, b) | 拼接路径 | 告诉管家"A区+B货架" |
os.mkdir(path) | 创建目录 | 新建一个货架 |
os.rmdir(path) | 删除空目录 | 拆掉空货架 |
2.2 示例
import os
# 查看当前目录
print(os.path.abspath('.')) # '/Users/michael'
# 拼接路径(自动处理分隔符)
new_dir = os.path.join('/Users/michael', 'testdir')
print(new_dir) # '/Users/michael/testdir'(Mac)或 'C:\\Users\\michael\\testdir'(Windows)
# 创建目录
os.mkdir(new_dir)
# 删除空目录
os.rmdir(new_dir)关键:路径拼接必须用 os.path.join(),不要手动写 '/' 或 '\\'——不同系统分隔符不同。
三、路径拆分:找文件名、找扩展名
3.1 os.path.split():拆目录和文件名
os.path.split('/Users/michael/testdir/file.txt')
# ('/Users/michael/testdir', 'file.txt')生活化理解:像快递单号拆分——"仓库地址 + 包裹编号"。
3.2 os.path.splitext():拆文件名和扩展名
os.path.splitext('/path/to/file.txt')
# ('/path/to/file', '.txt')适用:快速判断文件类型、批量修改扩展名。
注意:这些函数只操作字符串,不要求文件真实存在。
四、文件操作:重命名、删除、复制
4.1 os 模块自带
# 重命名
os.rename('test.txt', 'test.py')
# 删除
os.remove('test.py')4.2 复制文件:shutil 模块
import shutil
shutil.copyfile('source.txt', 'dest.txt')为什么复制不在 os 里? 因为复制不是操作系统的"系统调用",而是"读源文件 + 写目标文件"的组合操作——shutil 是 os 的"补充工具箱"。
五、文件筛选:一行代码找文件
5.1 列出所有目录
[x for x in os.listdir('.') if os.path.isdir(x)]
# ['.lein', '.local', '.m2', '.npm', '.ssh', ...]5.2 列出所有 .py 文件
[x for x in os.listdir('.') if os.path.isfile(x) and os.path.splitext(x)[1] == '.py']
# ['apis.py', 'config.py', 'models.py', ...]核心:os.listdir() 列出所有,os.path.isdir() / os.path.isfile() 判断类型,os.path.splitext() 筛扩展名——列表推导式一行搞定。
六、知识链条:从"我在哪"到"我要找什么"
当前位置:os.path.abspath('.')
↓
目标路径:os.path.join(当前位置, '子目录')
↓
操作:os.mkdir() / os.rmdir() / os.rename() / os.remove()
↓
筛选:os.listdir() + os.path.isdir()/isfile() + os.path.splitext()
↓
复制:shutil.copyfile()(os 的补充)七、常见误区与避坑指南
7.1 误区一:路径拼接用字符串相加
# ❌ 危险
path = '/Users/michael' + '/' + 'testdir'
path = 'C:\\Users' + '\\' + 'michael' # Windows 专用修正:os.path.join() 自动适配系统。
7.2 误区二:删除非空目录用 os.rmdir()
os.rmdir('/Users/michael/non_empty_dir') # ❌ OSError: 目录非空修正:用 shutil.rmtree() 强制删除(谨慎!):
import shutil
shutil.rmtree('/Users/michael/non_empty_dir')7.3 误区三:以为 os.path.exists() 区分文件和目录
os.path.exists('/path/to/something') # 存在就 True,不管是文件还是目录修正:要区分用 os.path.isfile() 或 os.path.isdir()。
7.4 误区四:遍历目录时用相对路径判断
for x in os.listdir('subdir'):
print(os.path.isfile(x)) # ❌ 错!x 是相对当前目录,不是 subdir修正:用完整路径:
for x in os.listdir('subdir'):
full_path = os.path.join('subdir', x)
print(os.path.isfile(full_path))八、实际应用案例
案例 1:项目文件整理器
import os
import shutil
def organize_files(target_dir):
"""按扩展名整理目录下的文件到分类文件夹"""
if not os.path.exists(target_dir):
print(f'目录不存在: {target_dir}')
return
# 定义分类规则
categories = {
'图片': ['.jpg', '.jpeg', '.png', '.gif'],
'文档': ['.txt', '.md', '.doc', '.pdf'],
'代码': ['.py', '.js', '.html', '.css'],
'压缩包': ['.zip', '.tar', '.gz']
}
for filename in os.listdir(target_dir):
filepath = os.path.join(target_dir, filename)
# 跳过目录
if os.path.isdir(filepath):
continue
# 获取扩展名
_, ext = os.path.splitext(filename)
ext = ext.lower()
# 找到分类
category = '其他'
for cat, exts in categories.items():
if ext in exts:
category = cat
break
# 创建分类目录
cat_dir = os.path.join(target_dir, category)
if not os.path.exists(cat_dir):
os.mkdir(cat_dir)
# 移动文件
dest = os.path.join(cat_dir, filename)
shutil.move(filepath, dest)
print(f'移动: {filename} → {category}/')
# 使用
organize_files('/Users/michael/Downloads')生活化理解:整理器是"仓库分拣机器人"——按包裹类型(扩展名)自动分到不同货架(目录),你只需按按钮。
案例 2:查找大文件
import os
def find_large_files(start_dir, size_mb=100):
"""递归查找大于指定大小的文件"""
size_bytes = size_mb * 1024 * 1024
for root, dirs, files in os.walk(start_dir):
for filename in files:
filepath = os.path.join(root, filename)
try:
file_size = os.path.getsize(filepath)
if file_size > size_bytes:
size_mb_actual = file_size / (1024 * 1024)
relative_path = os.path.relpath(filepath, start_dir)
print(f'{relative_path}: {size_mb_actual:.1f} MB')
except OSError:
pass # 权限不足等错误跳过
# 使用
find_large_files('/Users/michael', size_mb=50)生活化理解:查找器是"仓库盘点员"——逐个货架检查,发现超重大箱子就记录位置。
九、实战练习
练习 1:实现 dir -l 输出
编写程序,列出当前目录下所有文件和目录的详细信息(名称、大小、类型、修改时间):
import os
from datetime import datetime
def list_dir_detail(path='.'):
# 你的代码
pass
list_dir_detail()参考答案
import os
from datetime import datetime
def list_dir_detail(path='.'):
for item in os.listdir(path):
item_path = os.path.join(path, item)
stat = os.stat(item_path)
# 类型
item_type = '目录' if os.path.isdir(item_path) else '文件'
# 大小
size = stat.st_size
# 修改时间
mtime = datetime.fromtimestamp(stat.st_mtime).strftime('%Y-%m-%d %H:%M:%S')
print(f'{item_type:4} {size:>10} bytes {mtime} {item}')
list_dir_detail()练习 2:递归查找文件
在当前目录及所有子目录下,查找文件名包含指定字符串的文件,打印相对路径:
import os
def find_files(keyword, start_dir='.'):
# 你的代码
pass
find_files('test')参考答案
import os
def find_files(keyword, start_dir='.'):
for root, dirs, files in os.walk(start_dir):
for filename in files:
if keyword in filename:
full_path = os.path.join(root, filename)
relative_path = os.path.relpath(full_path, start_dir)
print(relative_path)
find_files('test')十、小结
os模块:操作系统的遥控器,os.name判断系统类型,os.environ读环境变量;- 目录操作:
os.mkdir()创建、os.rmdir()删空目录、os.path.abspath()看当前位置; - 路径处理:必须用
os.path.join()拼接,os.path.split()拆目录/文件名,os.path.splitext()拆扩展名; - 文件操作:
os.rename()重命名、os.remove()删除、shutil.copyfile()复制; - 文件筛选:
os.listdir()+os.path.isdir()/isfile()+ 列表推导式,一行搞定; - 递归遍历:
os.walk()逐层深入,适合查找、统计、批量处理; - 核心原则:路径操作不拼字符串,文件筛选用列表推导,目录遍历用
os.walk()。
os 模块是程序的"文件管家"——让代码像资源管理器一样操作文件,但比手动点击快一万倍。