5分钟Python · 文件整理篇 | 看完就能用,每行代码都有注释
今天用Python写一个脚本,自动扫描文件夹,按文件类型分门别类,一键搞定。
预期效果
整理前:Downloads/├── 年会照片.jpg├── 报表.xlsx├── 合同.pdf├── 头像.png├── 简历.docx├── 安装包.exe├── 猫咪视频.mp4├── 周杰伦.mp3├── 资料.zip└── ... (还有90个文件)整理后:Downloads/├── 🖼️ 图片/│ ├── 年会照片.jpg│ └── 头像.png├── 📄 文档/│ ├── 报表.xlsx│ ├── 合同.pdf│ └── 简历.docx├── 🎵 音频/│ └── 周杰伦.mp3├── 🎬 视频/│ └── 猫咪视频.mp4├── 📦 压缩包/│ └── 资料.zip└── ⚙️ 程序/ └── 安装包.exe
核心逻辑:遍历文件夹,判断文件后缀,移动到对应文件夹。
完整代码(复制即用)
from pathlib import Pathimport shutilTYPE_MAP = {# 🖼️ 图片".jpg": "🖼️ 图片", ".jpeg": "🖼️ 图片", ".png": "🖼️ 图片",".gif": "🖼️ 图片", ".bmp": "🖼️ 图片", ".webp": "🖼️ 图片",".svg": "🖼️ 图片", ".ico": "🖼️ 图片",# 📄 文档".pdf": "📄 文档", ".doc": "📄 文档", ".docx": "📄 文档",".xls": "📄 文档", ".xlsx": "📄 文档", ".ppt": "📄 文档",".pptx": "📄 文档", ".txt": "📄 文档", ".md": "📄 文档",# 🎬 视频".mp4": "🎬 视频", ".avi": "🎬 视频", ".mkv": "🎬 视频",".mov": "🎬 视频", ".wmv": "🎬 视频", ".flv": "🎬 视频",".webm": "🎬 视频",# 🎵 音频".mp3": "🎵 音频", ".wav": "🎵 音频", ".flac": "🎵 音频",".aac": "🎵 音频", ".ogg": "🎵 音频", ".m4a": "🎵 音频",# 📦 压缩包".zip": "📦 压缩包", ".rar": "📦 压缩包", ".7z": "📦 压缩包",".tar": "📦 压缩包", ".gz": "📦 压缩包", ".bz2": "📦 压缩包",# ⚙️ 程序".exe": "⚙️ 程序", ".msi": "⚙️ 程序", ".py": "🐍 程序",".js": "⚙️ 程序", ".html": "⚙️ 程序", ".css": "⚙️ 程序",".json": "⚙️ 程序", ".xml": "⚙️ 程序",}deforganize(target_dir):"""按文件类型整理指定目录""" target = Path(target_dir) moved = 0 skipped = 0for file in target.iterdir():ifnot file.is_file():continue suffix = file.suffix.lower() category = TYPE_MAP.get(suffix, "📁 其他") dest_dir = target / category dest_dir.mkdir(exist_ok=True) dest = dest_dir / file.nameif dest.exists(): print(f"跳过(已存在): {file.name}") skipped += 1continue shutil.move(str(file), str(dest)) print(f"{file.name} -> {category}/") moved += 1 print(f"\n完成!整理了 {moved} 个文件,跳过 {skipped} 个重复文件。")if __name__ == "__main__":# 改成你的目标目录 organize(r"C:\Users\你的用户名\Downloads")
核心代码解析
① 分类配置:TYPE_MAP
TYPE_MAP = {".jpg": "🖼️ 图片",".pdf": "📄 文档",# ... 其他后缀}
字典的键是文件后缀名,值是目标文件夹名称。想添加新分类,直接加一行即可。
小技巧:文件夹名称带 Emoji 图标,在 Finder/资源管理器中更醒目,一眼就能找到。
② 遍历目录:iterdir()
for file in target.iterdir():
iterdir() 遍历当前目录下的所有内容,但不递归进入子文件夹。如果想把子文件夹里的文件也整理出来,可以改用 rglob("*")。
③ 判断文件:is_file()
ifnot file.is_file():continue
跳过子目录,只处理文件。避免把文件夹当成文件移动。
④ 获取后缀:suffix.lower()
suffix = file.suffix.lower()
提取文件后缀名并转小写,保证 .JPG 和 .jpg 都能匹配。
⑤ 查分类:dict.get()
category = TYPE_MAP.get(suffix, "📁 其他")
用 get() 方法查字典,找不到匹配就归入"其他"文件夹,不会报错。
⑥ 拼接路径:Path / str
dest_dir = target / category
pathlib 用 / 拼接路径,比 os.path.join() 更直观,且自动适配 Windows/Linux/macOS。
⑦ 创建目录:mkdir(exist_ok=True)
dest_dir.mkdir(exist_ok=True)
创建分类文件夹,如果已存在则跳过。脚本可以反复运行不会报错。
⑧ 同名保护:dest.exists()
if dest.exists(): print(f"跳过(已存在): {file.name}")continue
如果目标位置已有同名文件,跳过不覆盖,保护数据安全。
⑨ 移动文件:shutil.move()
shutil.move(str(file), str(dest))
相当于"剪切+粘贴",保留文件的修改时间等元数据。
按需调优、增强、完善
调优1:只整理部分类型
TYPE_MAP = {".jpg": "🖼️ 图片",".png": "🖼️ 图片",".pdf": "📄 文档",".docx": "📄 文档",}# 未列出的后缀不会被移动
调优2:按日期归档
import datetimedeforganize_by_date(target_dir): target = Path(target_dir)for file in target.iterdir():ifnot file.is_file():continue mtime = datetime.datetime.fromtimestamp(file.stat().st_mtime) date_dir = target / f"{mtime.year}年{mtime.month:02d}月" date_dir.mkdir(exist_ok=True) shutil.move(str(file), str(date_dir / file.name))
调优3:递归处理所有子目录
for file in target.rglob("*"):if file.is_file():# 其他逻辑不变
调优4:一键恢复
运行前加一个日志记录,后悔了可以一键还原:
import jsondeforganize_with_log(target_dir): target = Path(target_dir) log = {}# ... 移动文件时记录 log[str(file)] = str(dest)with open("organize_log.json", "w", encoding="utf-8") as f: json.dump(log, f, ensure_ascii=False, indent=2)defundo(log_file="organize_log.json"):with open(log_file, "r", encoding="utf-8") as f: log = json.load(f)for src, dest in log.items():if Path(dest).exists(): shutil.move(dest, src)
调优5:打包成 exe 发给同事
pip install pyinstallerpyinstaller --onefile --name 文件整理器 organize.py
可能的问题
Q:报错 Permission denied 怎么办?
有些文件正在被占用(比如打开的 Excel)。关闭相关程序再运行,或用管理员权限运行。
Q:路径包含中文会报错吗?
不会。pathlib 原生支持 Unicode,中文路径完全没问题。
Q:运行后文件不见了?
文件被移动到了对应的分类文件夹里,去 图片/、文档/ 等目录下找。
Q:Emoji 显示为方块?
部分旧系统/终端不支持 Emoji,把 TYPE_MAP 里的图标改成纯文字即可:
".jpg": "图片", ".pdf": "文档",