查看: 99|回复: 3

Python文件批量整理实战:批量重命名、按类型归档与哈希去重

[复制链接]
发表于 2 小时前 | 显示全部楼层 |阅读模式
电脑用久了,桌面和下载文件夹里总会堆积大量混乱的文件,比如“新建文件夹 (1)”“最终版2”等。利用 Python 标准库的 os、shutil、hashlib、datetime 等模块,只需几十行代码就能实现批量重命名、按类型归档、删除重复文件(基于文件名+大小或内容哈希)、按日期归档、清空空文件夹等自动整理操作。以下代码均可在 Windows/Linux/macOS 下运行,建议先开启 dry_run 预览再实际执行。

一、批量重命名

1. 统一命名规则

函数 batch_rename 接收目录、前缀、起始编号和编号位数,将文件按修改时间排序后依次重命名。
  1. import os
  2. def batch_rename(directory, prefix="file", start=1, digits=3):
  3.     files = [f for f in os.listdir(directory) if os.path.isfile(os.path.join(directory, f))]
  4.     files.sort(key=lambda x: os.path.getmtime(os.path.join(directory, x)))
  5.     for i, filename in enumerate(files):
  6.         name, ext = os.path.splitext(filename)
  7.         new_name = f"{prefix}_{str(start + i).zfill(digits)}{ext}"
  8.         os.rename(os.path.join(directory, filename), os.path.join(directory, new_name))
  9.         print(f"{filename} → {new_name}")
  10. # 示例:将 D:/照片/2026婚纱照 下文件重命名为 wedding_001.jpg 等
  11. batch_rename("D:/照片/2026婚纱照", prefix="wedding", start=1, digits=3)
  12. # 示例:将课件重命名为 note_01.docx 等
  13. batch_rename("D:/下载/课件", prefix="note", start=1, digits=2)
复制代码

2. 添加日期前缀

使用 datetime.now() 获取当天日期,对未包含该前缀的文件添加“YYYYMMDD_”前缀。
  1. from datetime import datetime
  2. def add_date_prefix(directory):
  3.     today = datetime.now().strftime("%Y%m%d")
  4.     for f in os.listdir(directory):
  5.         filepath = os.path.join(directory, f)
  6.         if os.path.isfile(filepath) and not f.startswith(today):
  7.             new_name = f"{today}_{f}"
  8.             os.rename(filepath, os.path.join(directory, new_name))
  9.             print(f"添加前缀: {f} → {new_name}")
  10. add_date_prefix("D:/下载/课件")
复制代码

3. 批量替换文件名中的文字

替换文件名的任意子串,例如去掉“【课程资料】”或统一空格。
  1. def replace_filename_text(directory, old_text, new_text):
  2.     count = 0
  3.     for f in os.listdir(directory):
  4.         filepath = os.path.join(directory, f)
  5.         if os.path.isfile(filepath) and old_text in f:
  6.             new_name = f.replace(old_text, new_text)
  7.             os.rename(filepath, os.path.join(directory, new_name))
  8.             print(f"替换: {f} → {new_name}")
  9.             count += 1
  10.     print(f"共替换 {count} 个文件")
  11. replace_filename_text("D:/课件", "【课程资料】", "")
  12. replace_filename_text("D:/下载", "  ", " ")  # 双空格变单空格
复制代码

二、按类型自动归档

定义 EXTENSION_MAP 将文件扩展名映射到目标子文件夹,然后调用 shutil.move 移动文件。同名文件自动添加 _1 后缀。
  1. import shutil
  2. EXTENSION_MAP = {
  3.     ".jpg": "图片", ".jpeg": "图片", ".png": "图片",
  4.     ".gif": "图片", ".bmp": "图片", ".webp": "图片",
  5.     ".doc": "文档", ".docx": "文档", ".pdf": "文档",
  6.     ".xls": "表格", ".xlsx": "表格",
  7.     ".ppt": "演示文稿", ".pptx": "演示文稿",
  8.     ".txt": "文本", ".md": "文本",
  9.     ".zip": "压缩包", ".rar": "压缩包", ".7z": "压缩包",
  10.     ".mp4": "视频", ".avi": "视频", ".mov": "视频",
  11.     ".py": "代码", ".java": "代码", ".js": "代码",
  12.     ".html": "代码", ".css": "代码", ".sql": "代码",
  13. }
  14. def auto_sort_files(directory):
  15.     if not os.path.exists(directory):
  16.         print(f"文件夹不存在: {directory}")
  17.         return
  18.     moved_count = 0
  19.     for f in os.listdir(directory):
  20.         filepath = os.path.join(directory, f)
  21.         if not os.path.isfile(filepath):
  22.             continue
  23.         _, ext = os.path.splitext(f)
  24.         ext = ext.lower()
  25.         folder_name = EXTENSION_MAP.get(ext, "其他")
  26.         target_dir = os.path.join(directory, folder_name)
  27.         os.makedirs(target_dir, exist_ok=True)
  28.         target_path = os.path.join(target_dir, f)
  29.         if not os.path.exists(target_path):
  30.             shutil.move(filepath, target_path)
  31.         else:
  32.             name, ext = os.path.splitext(f)
  33.             target_path = os.path.join(target_dir, f"{name}_1{ext}")
  34.             shutil.move(filepath, target_path)
  35.         moved_count += 1
  36.     print(f"整理完成!{moved_count} 个文件已归档")
  37. auto_sort_files("D:/下载")
复制代码

三、删除重复文件

1. 按文件名+大小查找

用 os.walk 遍历所有文件,以 (文件名, 文件大小) 为键存入字典,遇到重复则记录。提供 dry_run 参数预览。
  1. def find_duplicates(directory):
  2.     files_info = {}
  3.     duplicates = []
  4.     for root, _, files in os.walk(directory):
  5.         for f in files:
  6.             filepath = os.path.join(root, f)
  7.             size = os.path.getsize(filepath)
  8.             key = (f, size)
  9.             if key in files_info:
  10.                 duplicates.append((filepath, files_info[key]))
  11.             else:
  12.                 files_info[key] = filepath
  13.     return duplicates
  14. def delete_duplicates(directory, dry_run=True):
  15.     duplicates = find_duplicates(directory)
  16.     if not duplicates:
  17.         print("没有找到重复文件")
  18.         return
  19.     print(f"找到 {len(duplicates)} 组重复文件:\n")
  20.     for dup, original in duplicates:
  21.         print(f"  保留: {original}")
  22.         print(f"  删除: {dup}\n")
  23.     if dry_run:
  24.         print(f"以上是预览结果,共可清理 {len(duplicates)} 个文件")
  25.         print(f"确认删除请运行: delete_duplicates('{directory}', dry_run=False)")
  26.     else:
  27.         for dup, _ in duplicates:
  28.             os.remove(dup)
  29.         print(f"已删除 {len(duplicates)} 个重复文件")
  30. delete_duplicates("D:/照片", dry_run=True)
复制代码

2. 按内容哈希(MD5)查找更准确

即使文件名不同,只要内容完全一致也能识别。
  1. import hashlib
  2. def find_duplicates_by_hash(directory):
  3.     hash_map = {}
  4.     duplicates = []
  5.     for root, _, files in os.walk(directory):
  6.         for f in files:
  7.             filepath = os.path.join(root, f)
  8.             try:
  9.                 with open(filepath, "rb") as fh:
  10.                     file_hash = hashlib.md5(fh.read()).hexdigest()
  11.             except:
  12.                 continue
  13.             if file_hash in hash_map:
  14.                 duplicates.append((filepath, hash_map[file_hash]))
  15.             else:
  16.                 hash_map[file_hash] = filepath
  17.     return duplicates
复制代码

四、按日期归档

根据文件修改时间,按“年+月”创建子文件夹,将指定扩展名的文件移入。
  1. def archive_by_month(directory, file_extensions=None):
  2.     if file_extensions is None:
  3.         file_extensions = [".jpg", ".jpeg", ".png", ".gif", ".mp4"]
  4.     moved = 0
  5.     for f in os.listdir(directory):
  6.         filepath = os.path.join(directory, f)
  7.         if not os.path.isfile(filepath):
  8.             continue
  9.         _, ext = os.path.splitext(f)
  10.         if ext.lower() not in file_extensions:
  11.             continue
  12.         mtime = os.path.getmtime(filepath)
  13.         year_month = datetime.fromtimestamp(mtime).strftime("%Y年%m月")
  14.         target_dir = os.path.join(directory, year_month)
  15.         os.makedirs(target_dir, exist_ok=True)
  16.         shutil.move(filepath, os.path.join(target_dir, f))
  17.         moved += 1
  18.     print(f"已归档 {moved} 个文件")
  19. archive_by_month("D:/照片")
复制代码

五、清空空文件夹

递归遍历目录,从最底层删除空文件夹。
  1. def remove_empty_dirs(directory):
  2.     removed = 0
  3.     for root, dirs, files in os.walk(directory, topdown=False):
  4.         for d in dirs:
  5.             dirpath = os.path.join(root, d)
  6.             try:
  7.                 if not os.listdir(dirpath):
  8.                     os.rmdir(dirpath)
  9.                     print(f"删除空文件夹: {dirpath}")
  10.                     removed += 1
  11.             except:
  12.                 pass
  13.     print(f"共删除 {removed} 个空文件夹")
复制代码

六、一键整理桌面

组合上述功能,先按类型归档,再删空文件夹,最后查找重复文件。
  1. def clean_desktop():
  2.     desktop = os.path.expanduser("~/Desktop")
  3.     print(f"整理桌面: {desktop}")
  4.     auto_sort_files(desktop)
  5.     remove_empty_dirs(desktop)
  6.     duplicates = find_duplicates(desktop)
  7.     if duplicates:
  8.         print(f"桌面有 {len(duplicates)} 组重复文件")
  9.         for d, o in duplicates[:5]:
  10.             print(f"  {os.path.basename(d)}")
  11.     else:
  12.         print("无重复文件")
  13.     print("桌面整理完成!")
  14. # 谨慎使用:会移动桌面上所有文件
  15. # clean_desktop()
复制代码

七、文件整理工具箱类

将常用操作封装为 FileOrganizer 类,支持预览文件统计和一键整理。
  1. class FileOrganizer:
  2.     def __init__(self, base_dir):
  3.         self.base_dir = base_dir
  4.     def preview(self):
  5.         total = 0
  6.         ext_count = {}
  7.         for f in os.listdir(self.base_dir):
  8.             fp = os.path.join(self.base_dir, f)
  9.             if os.path.isfile(fp):
  10.                 total += 1
  11.                 _, ext = os.path.splitext(f)
  12.                 ext_count[ext] = ext_count.get(ext, 0) + 1
  13.         print(f"📁 {self.base_dir}")
  14.         print(f"📄 共 {total} 个文件")
  15.         for ext, cnt in sorted(ext_count.items(), key=lambda x: -x[1])[:10]:
  16.             print(f"  {ext}: {cnt}个")
  17.     def organize(self):
  18.         print("开始整理...")
  19.         auto_sort_files(self.base_dir)
  20.         remove_empty_dirs(self.base_dir)
  21.         print("整理完成!")
  22. org = FileOrganizer("D:/下载")
  23. org.preview()
  24. org.organize()
复制代码

总结

日常文件整理最常用的三个场景:batch_rename(批量重命名)、auto_sort_files(按类型归档)、find_duplicates(查找重复)。务必先用 dry_run=True 预览效果,确认无误后再执行删除或移动操作。以上所有脚本均基于 Python 3 标准库,无需额外安装第三方包,可在任意环境下直接运行。
回复

使用道具 举报

发表于 2 小时前 | 显示全部楼层

Re: Python文件批量整理实战:批量重命名、按类型归档与哈希去重

这个帖子非常实用,代码直接能跑,而且考虑到了dry_run预览(虽然示例里没写但楼主提了建议先预览)。批量重命名和按类型归档正是我经常需要的功能,尤其是用哈希去重清理重复文件,能省下不少磁盘空间。请问楼主,在按日期归档那块有没有考虑过让用户自定义日期格式和归档目录结构(比如年/月/日)?另外,哈希去重是只对比文件名和大小,还是也做了内容哈希?如果只靠文件名+大小,可能会有误判。期待更详细的实现。
回复 支持 反对

使用道具 举报

发表于 2 小时前 | 显示全部楼层

Re: Python文件批量整理实战:批量重命名、按类型归档与哈希去重

很棒的文章,代码简洁实用,尤其是 dry_run 预览这点很贴心,能防止误操作。想请教一下,如果目录里包含子文件夹,目前只处理了根目录下的文件,有没有考虑过用 os.walk 实现递归遍历,这样整理桌面或下载目录时会更彻底?另外替换文件名那里,如果 old_text 是正则的话会不会更灵活?期待后续更新。
回复 支持 反对

使用道具 举报

发表于 2 小时前 | 显示全部楼层

Re: Python文件批量整理实战:批量重命名、按类型归档与哈希去重

感谢分享,很实用的实战技巧,代码清晰易懂。有个问题想请教:你说的 dry_run 预览模式具体怎么实现?在代码里没有看到相关的参数,是不是要自己加一个判断,用 print 代替 rename/move 来模拟?另外,按类型归档时,如果目标文件夹已经存在同名文件,代码里只是加了 `_1` 后缀,有没有考虑加编号递增避免覆盖?
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

指导单位

江苏省公安厅

江苏省通信管理局

浙江省台州刑侦支队

DEFCON GROUP 86025

Hacking Group 021A

旗下站点

态势感知中心

应急响应中心

红盟安全

联系我们

官方QQ群:112851260

官方邮箱:security#ihonker.org(#改成@)

官方核心成员

关注微信公众号

Archiver|手机版|小黑屋| ( 沪ICP备2021026908号 )

GMT+8, 2026-7-3 14:37 , Processed in 0.029454 second(s), 18 queries , Gzip On, Redis On.

Powered by ihonker.com

Copyright © 2015-现在.

  • 返回顶部