
这是什么:一个只干一件事的小工具
每个人的下载文件夹最后都会变成同一个样子:安装包、截图、PDF、压缩包混在一起,找东西全靠搜索框,删东西又怕误删。这个小工具只干一件事——把下载文件夹里的文件按类型分进不同的子文件夹:图片进“图片”,文档进“文档”,压缩包进“压缩包”,以此类推。
它不联网、不装任何第三方库,只用 Python 自带的标准库,代码 30 行左右,改两行就能按自己的习惯调整分类。前置知识只需要两点:电脑上装了 Python 3,会打开终端(命令行)输入命令。没有装 Python 的话,先去 Python 官网下载安装,安装时勾选把 Python 加到系统 PATH。
完整代码:复制下来就能跑
把下面这段代码保存为 organize.py,放在哪里都行,不用和下载文件夹放一起:
#!/usr/bin/env python3
"""把下载文件夹按类型自动归档:干跑先看,确认后再动真格。"""
import argparse, shutil
from pathlib import Path
RULES = {
"图片": {".jpg", ".jpeg", ".png", ".gif", ".webp", ".heic"},
"文档": {".pdf", ".doc", ".docx", ".xls", ".xlsx", ".ppt", ".pptx", ".txt", ".md"},
"压缩包": {".zip", ".rar", ".7z", ".tar", ".gz"},
"视频": {".mp4", ".mkv", ".mov", ".avi"},
"音频": {".mp3", ".flac", ".wav", ".aac"},
"安装包": {".exe", ".msi", ".dmg", ".pkg", ".apk"},
}
SKIP_SUFFIXES = {".part", ".crdownload", ".tmp", ".download"}
def classify(p: Path) -> str:
for folder, exts in RULES.items():
if p.suffix.lower() in exts:
return folder
return "其他"
def unique(target: Path) -> Path:
if not target.exists():
return target
n = 2
while True:
cand = target.with_name(f"{target.stem}-{n}{target.suffix}")
if not cand.exists():
return cand
n += 1
def main():
ap = argparse.ArgumentParser()
ap.add_argument("src", help="下载文件夹路径")
ap.add_argument("--go", action="store_true", help="不加 --go 只干跑、不移动文件")
args = ap.parse_args()
src = Path(args.src).expanduser()
moved = skipped = 0
for p in sorted(src.iterdir()):
if not p.is_file() or p.name.startswith("."):
skipped += 1
continue
if p.suffix.lower() in SKIP_SUFFIXES:
print(f"跳过(未下载完):{p.name}")
skipped += 1
continue
dest = unique(src / classify(p) / p.name)
if args.go:
dest.parent.mkdir(parents=True, exist_ok=True)
shutil.move(str(p), str(dest))
print(f"{p.name} -> {dest.relative_to(src)}")
moved += 1
print(f"共 {moved} 个文件,跳过 {skipped} 个" + ("(已移动)" if args.go else "(干跑,未移动)"))
if __name__ == "__main__":
main()
怎么用:先干跑,确认无误再动真格
整理文件的工具最怕一点:还没看清它要干什么,文件已经被挪走了。所以这个脚本默认是干跑模式,只打印计划、不移动任何文件:
python3 organize.py ~/Downloads
终端会逐行打印 report.pdf -> 文档/report.pdf 这样的计划。确认没问题,再加 --go 真正执行:
python3 organize.py ~/Downloads --go
把 ~/Downloads 换成你自己的下载文件夹路径即可。Windows 用户把路径换成类似 C:\Users\你的用户名\Downloads 的形式,注意先干跑一次。
三个容易踩坑的细节,它都处理了
第一,未下载完的文件不动。 浏览器下载中的文件会带 .part、.crdownload 这类临时后缀,脚本会直接跳过并打印提示,不会把一个只下了一半的文件归档成“完成品”。
第二,重名文件不覆盖。 目标文件夹里已经有个同名文件时,新文件会自动改成 report-2.pdf、report-3.pdf,而不是悄悄覆盖旧文件。旧文件永远不会因为一次归档而丢失。
第三,只动顶层文件,不碰子文件夹和隐藏文件。 已经分好类的子文件夹、系统隐藏文件都原样不动。脚本认的是文件后缀:后缀不在规则表里的,一律进“其他”,不会被删掉或乱丢。
实测结果
我在测试文件夹里放了 8 个文件(PDF、图片、压缩包、音频、视频、安装包各一份,外加一个 .part 临时文件和一个隐藏文件),先干跑确认计划无误,再用 --go 执行:8 个文件全部按类型进了对应子文件夹,临时文件和隐藏文件原样留在原地。之后又往根目录放了一个同名 report.pdf 再跑一次,它被正确归档为 文档/report-2.pdf,原文件安然无恙。
还能怎么改:两处就够
- 改分类:往
RULES里加一行就行,比如把.epub、.mobi归进“电子书”,把.psd归进“设计”。 - 定时跑:觉得手动跑麻烦,可以把它挂到系统的定时任务里每周跑一次(Linux 和 macOS 用 cron,Windows 用任务计划程序),每次跑之前它还是会先打印计划,日志留着,出问题能回查。
最后提醒一句:第一次用任何整理脚本之前,先对下载文件夹做一次备份,或者先在复制出来的测试文件夹里跑一遍。工具的价值是省时间,不是制造一次“文件去哪了”的寻宝游戏。
