news 2026/9/4 5:03:59

【Python项目实战】项目·下载文件夹整理助手:pathlib按类型自动归类

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【Python项目实战】项目·下载文件夹整理助手:pathlib按类型自动归类

下载文件夹里300个文件躺成一片,找一张上周的截图要翻两分钟?

今天写一个“自动收纳师”,写完当天就能用上

🎯本篇成品:一条命令按类型整理任意文件夹——图片、文档、压缩包各归各位,重名文件绝不覆盖。还带预览模式:先看它打算干什么,再决定让它干。含注释120行左右。


📌 太长不看版(给想快速上手的你)

项目信息一句话说明
项目名称下载文件夹整理助手(File Organizer)
代码行数~120行(含注释)
依赖零依赖,Python自带模块
核心功能按扩展名自动归类 + 重名保护 + 预览模式
跑起来的命令python main.py ~/Downloads --dry-run(先预览再执行)
技术点pathlibshutil.moveargparse开关参数
做完你能得到第一个能真正改变你电脑文件的工具

一、成品预览

$ python main.py ~/Downloads --dry-run [预览] 报告.pdf → 文档/ [预览] IMG_2026.jpg → 图片/ [预览] setup.exe → 安装包/ [预览] 神曲.mp3 → 音频/ [预览] 未命名.psd → 其他/ —— 预览 5 个文件,未做任何改动 —— (预览模式:未做任何改动;去掉 --dry-run 正式执行) $ python main.py ~/Downloads 已移动:报告.pdf → 文档/ 已移动:IMG_2026.jpg → 图片/ 已移动:setup.exe → 安装包/ 已移动:神曲.mp3 → 音频/ 已移动:未命名.psd → 其他/ —— 整理 5 个文件 —— $ ls ~/Downloads # Windows用dir 文档 图片 安装包 音频 其他

🚀 和上一篇的待办清单比,这个项目特殊在哪?

⚠️它会动你磁盘上的真实文件。所以本篇除了代码,还有三个安全设计

安全设计作用
🛡️预览模式(dry-run)先看它打算干什么,确认无误再执行
🛡️重名不覆盖两个报告.pdf→ 第二个自动变报告(1).pdf
🛡️只动文件不递归只整理当前层,不动子文件夹里的文件

这三个习惯,会让你以后写的每一个“会改东西”的脚本都值得信任。


二、前置知识:pathlib四件套 + 一个搬运工

上一项目见过Path,这次用它的四个核心技能

技能写法说明
遍历文件夹folder.iterdir()逐个给出里面的文件和文件夹
判断item.is_dir()/dest.exists()是文件夹吗 / 路径存在吗
拆文件名item.suffix/item.stem报告.pdf→ 后缀".pdf"、名字"报告"
换个名字dest.with_name("新名.pdf")同文件夹下改个名字

再配一个搬运工:shutil.move(源, 目标)—— 把文件从一个路径移到另一个路径。

⚠️注意item.suffix返回的后缀自带一个点".pdf"而不是"pdf")。记住这个细节,第九节③有个著名的坑等着它。


三、第0步:setup(3分钟,流程已是老朋友)

1. 新建文件夹organizer,VSCode打开 2. python -m venv venv 3. 激活:windows: venv\Scripts\activate(cmd) | .\venv\Scripts\Activate.ps1(PowerShell) mac: source venv/bin/activate 4. git init,写好.gitignore 5. 新建空文件:main.py

💡 零依赖项目,venv照建——习惯不因项目而变。


四、第1步:规则表——把"分类逻辑"写成一份数据

先别急着写功能代码。分类的本质是什么?查表:拿到扩展名,查它属于哪一类。那就把表写出来:

"""organizer —— 下载文件夹整理助手"""importargparseimportshutilfrompathlibimportPath# 扩展名 → 文件夹 的归类规则(想加类别,在这里加一行就行)RULES={"图片":[".jpg",".jpeg",".png",".gif",".webp",".bmp"],"文档":[".pdf",".docx",".doc",".txt",".md",".xlsx",".pptx"],"压缩包":[".zip",".rar",".7z",".tar",".gz"],"安装包":[".exe",".msi",".dmg",".pkg"],"视频":[".mp4",".mkv",".mov",".avi"],"音频":[".mp3",".wav",".flac",".m4a"],}defclassify(suffix:str)->str:"""查规则表:这个扩展名该进哪个文件夹;都不认识就进"其他" """forfolder,extsinRULES.items():ifsuffix.lower()inexts:# .lower() 让 .JPG 和 .jpg 一视同仁returnfolderreturn"其他"

🎯 体会一下这个设计

好在哪里说明
数据驱动分类规则全在RULES里,classify只是查表的人
易扩展以后想加“电子书”类别,改数据就行,一行逻辑代码都不用动
容错suffix.lower().JPG.jpg一视同仁

💡把变化放进数据,把逻辑写成通用——这是好程序的第一个形状。


五、第2步:重名保护——数据无价(重点!)

如果不做任何保护,两个都叫报告.pdf的文件,后到的会悄悄覆盖先到的——没有任何提示,丢了就是丢了。

defunique_path(dest:Path)->Path:"""目标已存在就起个不重名的新名字:报告.pdf → 报告(1).pdf"""ifnotdest.exists():returndest stem,ext=dest.stem,dest.suffix n=1whileTrue:candidate=dest.with_name(f"{stem}({n}){ext}")ifnotcandidate.exists():returncandidate n+=1

逻辑简单粗暴:

报告.pdf 被占了 → 试试 报告(1).pdf 报告(1).pdf 也被占了 → 试试 报告(2).pdf 直到没人用为止 ✅

🚨 以后你写任何涉及移动、复制、写文件的代码,都先想想这句口诀:

📌写文件操作前,先问“会不会覆盖”。


六、第3步:主流程——遍历、跳过、预览或搬移

deforganize(folder:Path,dry_run:bool=False):"""主流程:遍历 → 分类 → 预览或搬移"""moved=0foriteminsorted(folder.iterdir()):# 跳过文件夹和隐藏文件(.DS_Store这类)ifitem.is_dir()oritem.name.startswith("."):continuetarget_dir=folder/classify(item.suffix)dest=unique_path(target_dir/item.name)ifdry_run:print(f"[预览]{item.name}{target_dir.name}/")else:target_dir.mkdir(exist_ok=True)# 文件夹不存在就建shutil.move(str(item),str(dest))print(f"已移动:{item.name}{target_dir.name}/")moved+=1action="预览"ifdry_runelse"整理"print(f"——{action}{moved}个文件 ——")ifdry_run:print("(预览模式:未做任何改动;去掉 --dry-run 正式执行)")

📌 三个安全细节都在这一段里

安全点代码作用
不搬文件夹if item.is_dir(): continue包括我们自己生成的归类文件夹,不会搬自己家
不搬隐藏文件if item.name.startswith(".")跳过Mac的.DS_Store等系统文件
预览/执行分离if dry_run:同一个逻辑,只差“搬”这一个动作

🎯预览模式的精髓:计划与执行分离。先看计划,再决定是否执行。


七、第4步:argparse接上两个开关

defmain():parser=argparse.ArgumentParser(description="下载文件夹整理助手")parser.add_argument("folder",nargs="?",default=".",help="要整理的文件夹路径,默认当前目录")parser.add_argument("--dry-run",action="store_true",help="预览模式:只显示计划,不动任何文件")args=parser.parse_args()folder=Path(args.folder).expanduser()# ~ 自动展开成用户主目录ifnotfolder.is_dir():print(f"文件夹不存在:{folder}")returnorganize(folder,dry_run=args.dry_run)if__name__=="__main__":main()

📌 两个新知识点

知识点写法效果
可选参数nargs="?"+default="."不传路径就整理当前目录
开关参数action="store_true"写了--dry-run它就是True,不写就是False
路径展开.expanduser()~翻译成你的主目录(/Users/你C:\Users\你

八、第5步:验收——先沙盒,后实战(重点!)

🚨文件操作脚本有一条铁律:先在沙盒里验证,再上真实数据。千万别拿下载文件夹当小白鼠。

第一步:造一个沙盒并塞满假文件

VSCode终端执行:

# 建沙盒mkdirsandbox&&cdsandbox# 造假文件(Windows用 echo hi> 文件名)echohi>报告.pdfechohi>神曲.mp3echohi>setup.exeechohi>IMG_001.jpgechohi>未知.xyz# 回到项目根目录cd..

第二步:沙盒里先预览再实跑

python main.py sandbox --dry-run# 看计划:5个文件各归各类python main.py sandbox# 正式执行lssandbox# 图片/ 音频/ 安装包/ 文档/ 其他/,全齐

第三步:真实战场,先预览

python main.py ~/Downloads --dry-run

盯着清单看10秒——有没有不该动的文件?确认无误,去掉--dry-run正式执行。

🎉 从此你的下载文件夹,一条命令治好


九、常见报错:这6个,全是“动文件”脚本的高发区(重点!)

① 路径带空格被切断:C:\Users\my name\Downloads只认出了C:\Users\my

🔍 原因:空格是参数分隔符。

✅ 解法:整个路径套引号

python main.py"C:\Users\my name\Downloads"

PermissionError: [Errno 13],移动到一半中断

🔍 原因:文件正被别的程序占用——PDF还开着、视频还在播放器里、下载还没完成。

✅ 解法

  1. 关掉占用它的程序再跑;
  2. 本脚本可以放心重跑:已搬好的会跳过(在文件夹里,是目录),没搬的继续搬。

③ 所有文件都进了"其他"

🔍 原因:规则表里写的是"pdf",不是".pdf"——suffix自带点(.pdf),查表永远查不中。

✅ 解法:用断点法,盯一眼item.suffix的真实长相,和你规则表里的键对一对。

📌数据对不上,先看数据的真实形状。


④ 手机拍的.JPG全进了“其他”

🔍 原因classify里忘了suffix.lower(),大写后缀查不到表。

✅ 解法:代码里已经防了;如果你自查,造一个.JPG假文件跑沙盒试试——这就是沙盒的第二个用处:给边界情况做回归测试


⑤ “其他”文件夹里混着.DS_Store(Mac)

🔍 原因:macOS会往文件夹里塞隐藏配置文件,它们也是“文件”,会被遍历到。

✅ 解法startswith(".")已经跳过它们。Windows的隐藏文件(desktop.ini)也可以按这个逻辑处理。


⑥ 自己写move没防重名,老文件被悄悄覆盖

🔍 原因shutil.move(item, target_dir / item.name)遇到同名文件时,行为会因操作系统而异——覆盖或报错,都不受你控制。

✅ 解法永远走unique_path再念一遍口诀:

🚨写文件操作前,先问“会不会覆盖”。


十、课后练习

#练习难度提示
1加类别:给RULES加“电子书”(.epub/.mobi/.azw3)和“代码”(.py/.ipynb/.html)改数据不改逻辑,体会有多爽
2安全升级:把默认行为改成“只预览”,加一个--yes参数才真正执行⭐⭐action="store_true",逻辑反过来
3自动化测试雏形:用循环造20个假文件,跑整理,断言各类别文件数正确⭐⭐⭐Path(f"报告{i}.pdf").touch()
4(选做)定时自动整理:Windows用“任务计划程序”,Mac用launchd,每天21:00自动执行⭐⭐⭐⭐务必先跑过--dry-run确认无误再上定时

📦 配套代码

完整main.py与沙盒测试脚本已上传GitHub(08-file-organizer/organizer):【https://gitee.com/xqshadow/python-project-in-practice】

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/4 5:03:36

Java随机算法笔记

Java中实现随机算法的方法 Collections.shuffle 【概率分布不是用的正态分布,而是能够保证平均分布的概率分布】 参考: https://www.php.cn/faq/2714877.html https://juejin.cn/post/7178693368506449976 https://zhuanlan.zhihu.com/p/73147939 https:…

作者头像 李华
网站建设 2026/9/4 5:03:36

斐波那契数列从整数到复数的扩展:数学原理与Python实现

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/4 5:02:15

AI时代程序员如何避免思维退化:从执行到思考的编码思维训练

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/4 5:01:57

FPGA手写DDS任意波形生成实战:从Verilog到示波器

简介:本资源是一套面向电子类本科毕设与FPGA课程设计的完整DDS任意波形发生器实现方案,聚焦数字信号合成核心原理与硬件落地能力培养。资源基于FPGA平台构建,涵盖相位累加器、波形查找表(LUT)、参数动态配置、DAC接口适…

作者头像 李华
网站建设 2026/9/4 4:59:41

AfterQuery估值32亿美元:数据库渲染如何重塑后端开发新范式

AfterQuery 这两天在科技资讯版块刷了一波存在感,原因不是发布了某个开源模型,而是一条融资传闻:以 32 亿美元估值成为 Y Combinator 史上最快独角兽。这个标题里其实藏着三个技术圈更关心的问题:这个公司是做什么的?它…

作者头像 李华
网站建设 2026/9/4 4:59:38

STM32蜂鸣器音乐播放:从定时器原理到完整工程实现

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华