10-实战项目1-自动整理文件夹
再也不用在10个群里找文件了!
你有没有过这样的经历:
- 下载文件夹里有几千个文件,找个东西要翻半天
- 图片、文档、视频混在一起,乱成一锅粥
- 想把照片按日期整理,一个一个移动累死
别再假装你会手动整理文件夹了,用Python吧!
今天我们做一个自动整理文件夹的工具,几秒钟就能把几千个文件分类整理好。
项目目标
实现一个自动整理文件夹的工具:
- 自动识别文件类型(图片、文档、视频、音乐等)
- 按类型把文件移动到对应的文件夹
- 支持自定义分类规则
- 支持预览将要执行的操作
- 可以回滚操作
完整代码
import os
import shutil
from datetime import datetime
import json
class FileOrganizer:
"""文件整理工具"""
def __init__(self, folder_path):
self.folder_path = folder_path
self.operations = [] # 记录所有操作,用于回滚
# 默认分类规则
self.rules = {
"图片": [".jpg", ".jpeg", ".png", ".gif", ".bmp", ".svg", ".webp"],
"文档": [".txt", ".doc", ".docx", ".pdf", ".xls", ".xlsx", ".ppt", ".pptx"],
"视频": [".mp4", ".avi", ".mov", ".mkv", ".flv", ".wmv"],
"音乐": [".mp3", ".wav", ".flac", ".aac", ".ogg"],
"压缩包": [".zip", ".rar", ".7z", ".tar", ".gz"],
"代码": [".py", ".js", ".html", ".css", ".java", ".c", ".cpp"]
}
# 加载自定义规则
self.load_rules()
def load_rules(self):
"""加载自定义分类规则"""
rules_file = os.path.join(self.folder_path, "organizer_rules.json")
if os.path.exists(rules_file):
try:
with open(rules_file, "r", encoding="utf-8") as f:
self.rules = json.load(f)
print("已加载自定义分类规则")
except Exception as e:
print(f"加载规则失败:{e}")
def save_rules(self):
"""保存自定义分类规则"""
rules_file = os.path.join(self.folder_path, "organizer_rules.json")
try:
with open(rules_file, "w", encoding="utf-8") as f:
json.dump(self.rules, f, ensure_ascii=False, indent=2)
print("分类规则已保存")
except Exception as e:
print(f"保存规则失败:{e}")
def get_file_type(self, filename):
"""根据文件名获取文件类型"""
_, ext = os.path.splitext(filename.lower())
for category, extensions in self.rules.items():
if ext in extensions:
return category
return "其他"
def scan_files(self):
"""扫描文件夹中的所有文件"""
files_info = []
for item in os.listdir(self.folder_path):
item_path = os.path.join(self.folder_path, item)
# 跳过文件夹
if os.path.isdir(item_path):
continue
# 跳过隐藏文件和规则文件
if item.startswith(".") or item == "organizer_rules.json":
continue
file_type = self.get_file_type(item)
files_info.append({
"name": item,
"type": file_type,
"path": item_path
})
return files_info
def preview_operations(self, files_info):
"""预览将要执行的操作"""
if not files_info:
print("没有需要整理的文件!")
return
print("\n=== 预览操作 ===")
print(f"共找到 {len(files_info)} 个文件需要整理\n")
# 按类型分组
type_groups = {}
for file_info in files_info:
file_type = file_info["type"]
if file_type not in type_groups:
type_groups[file_type] = []
type_groups[file_type].append(file_info)
# 显示每个类型的文件
for file_type, files in type_groups.items():
target_folder = os.path.join(self.folder_path, file_type)
print(f"\n【{file_type}】 -> {target_folder}")
for file_info in files:
print(f" - {file_info['name']}")
return type_groups
def organize(self, dry_run=False):
"""整理文件"""
if not os.path.exists(self.folder_path):
print(f"文件夹不存在:{self.folder_path}")
return False
# 扫描文件
files_info = self.scan_files()
if not files_info:
print("没有需要整理的文件!")
return False
# 预览操作
type_groups = self.preview_operations(files_info)
if dry_run:
print("\n【预览模式】不会实际执行操作")
return True
# 确认操作
print("\n=== 开始整理 ===")
confirm = input("确定要整理吗?(输入yes确认):")
if confirm.lower() != "yes":
print("操作已取消")
return False
# 执行整理
success_count = 0
error_count = 0
for file_type, files in type_groups.items():
# 创建目标文件夹
target_folder = os.path.join(self.folder_path, file_type)
os.makedirs(target_folder, exist_ok=True)
# 移动文件
for file_info in files:
try:
old_path = file_info["path"]
new_path = os.path.join(target_folder, file_info["name"])
# 检查文件是否已存在
if os.path.exists(new_path):
print(f"跳过(文件已存在):{file_info['name']}")
continue
# 移动文件
shutil.move(old_path, new_path)
# 记录操作(用于回滚)
self.operations.append({
"old_path": old_path,
"new_path": new_path,
"timestamp": datetime.now().isoformat()
})
print(f"移动:{file_info['name']} -> {file_type}/")
success_count += 1
except Exception as e:
print(f"移动失败 {file_info['name']}:{e}")
error_count += 1
# 保存操作记录
self.save_operations()
print(f"\n整理完成!成功:{success_count},失败:{error_count}")
return True
def save_operations(self):
"""保存操作记录"""
if not self.operations:
return
record_file = os.path.join(self.folder_path, "organizer_record.json")
try:
with open(record_file, "w", encoding="utf-8") as f:
json.dump(self.operations, f, ensure_ascii=False, indent=2)
print(f"操作记录已保存到:{record_file}")
except Exception as e:
print(f"保存操作记录失败:{e}")
def rollback(self):
"""回滚操作"""
record_file = os.path.join(self.folder_path, "organizer_record.json")
if not os.path.exists(record_file):
print("没有找到操作记录,无法回滚")
return
try:
with open(record_file, "r", encoding="utf-8") as f:
operations = json.load(f)
if not operations:
print("没有可回滚的操作")
return
print(f"\n=== 回滚操作 ===")
print(f"共找到 {len(operations)} 个操作需要回滚")
confirm = input("确定要回滚吗?(输入yes确认):")
if confirm.lower() != "yes":
print("回滚已取消")
return
success_count = 0
error_count = 0
for op in reversed(operations):
try:
old_path = op["old_path"]
new_path = op["new_path"]
if os.path.exists(new_path):
shutil.move(new_path, old_path)
print(f"回滚:{os.path.basename(new_path)}")
success_count += 1
else:
print(f"跳过(文件不存在):{os.path.basename(new_path)}")
except Exception as e:
print(f"回滚失败:{e}")
error_count += 1
print(f"\n回滚完成!成功:{success_count},失败:{error_count}")
# 删除操作记录
os.remove(record_file)
print("操作记录已删除")
except Exception as e:
print(f"回滚失败:{e}")
def add_rule(self, category, extensions):
"""添加分类规则"""
extensions = [ext if ext.startswith(".") else f".{ext}" for ext in extensions]
if category not in self.rules:
self.rules[category] = []
for ext in extensions:
if ext not in self.rules[category]:
self.rules[category].append(ext)
self.save_rules()
print(f"已添加规则:【{category}】{extensions}")
def remove_rule(self, category, extensions):
"""删除分类规则"""
if category not in self.rules:
print(f"分类【{category}】不存在")
return
for ext in extensions:
ext = ext if ext.startswith(".") else f".{ext}"
if ext in self.rules[category]:
self.rules[category].remove(ext)
# 如果分类下没有扩展名了,删除分类
if not self.rules[category]:
del self.rules[category]
self.save_rules()
print(f"已删除规则:【{category}】{extensions}")
def show_rules(self):
"""显示所有分类规则"""
print("\n=== 当前分类规则 ===")
for category, extensions in self.rules.items():
print(f"\n【{category}】")
for ext in extensions:
print(f" - {ext}")
def main():
"""主函数"""
print("=== 文件整理工具 ===\n")
# 输入文件夹路径
folder_path = input("请输入要整理的文件夹路径(直接回车使用当前目录):")
if not folder_path.strip():
folder_path = os.getcwd()
print(f"使用当前目录:{folder_path}")
# 创建整理工具
organizer = FileOrganizer(folder_path)
while True:
print("\n=== 主菜单 ===")
print("1. 预览操作")
print("2. 开始整理")
print("3. 回滚操作")
print("4. 查看分类规则")
print("5. 添加分类规则")
print("6. 删除分类规则")
print("7. 退出")
choice = input("\n请选择操作(1-7):")
if choice == "1":
files_info = organizer.scan_files()
organizer.preview_operations(files_info)
elif choice == "2":
dry_run = input("是否只预览不执行?(yes/no):").lower() == "yes"
organizer.organize(dry_run)
elif choice == "3":
organizer.rollback()
elif choice == "4":
organizer.show_rules()
elif choice == "5":
category = input("请输入分类名称:")
extensions = input("请输入扩展名(用空格分隔,如 jpg png):").split()
organizer.add_rule(category, extensions)
elif choice == "6":
category = input("请输入分类名称:")
extensions = input("请输入要删除的扩展名(用空格分隔):").split()
organizer.remove_rule(category, extensions)
elif choice == "7":
print("退出程序!")
break
else:
print("无效的选择,请重新输入")
if __name__ == "__main__":
main()
使用示例
1. 整理下载文件夹
# 简单使用
organizer = FileOrganizer("/Users/yourname/Downloads")
organizer.organize()
2. 预览操作
organizer = FileOrganizer("/Users/yourname/Downloads")
organizer.organize(dry_run=True) # 只预览,不执行
3. 自定义分类规则
organizer = FileOrganizer("/Users/yourname/Downloads")
# 添加新的分类
organizer.add_rule("设计文件", ["psd", "ai", "sketch"])
# 删除规则
organizer.remove_rule("图片", ["bmp", "svg"])
4. 回滚操作
organizer = FileOrganizer("/Users/yourname/Downloads")
organizer.rollback()
进阶功能:按日期整理照片
import os
import shutil
from datetime import datetime
def organize_photos_by_date(folder_path):
"""按日期整理照片"""
image_extensions = [".jpg", ".jpeg", ".png", ".heic"]
for filename in os.listdir(folder_path):
filepath = os.path.join(folder_path, filename)
# 跳过文件夹
if not os.path.isfile(filepath):
continue
# 只处理图片文件
_, ext = os.path.splitext(filename.lower())
if ext not in image_extensions:
continue
# 获取文件修改时间
file_time = os.path.getmtime(filepath)
date = datetime.fromtimestamp(file_time)
date_folder = date.strftime("%Y-%m-%d")
# 创建日期文件夹
target_folder = os.path.join(folder_path, date_folder)
os.makedirs(target_folder, exist_ok=True)
# 移动文件
target_path = os.path.join(target_folder, filename)
shutil.move(filepath, target_path)
print(f"移动:{filename} -> {date_folder}/")
print("整理完成!")
# 使用示例
organize_photos_by_date("/Users/yourname/Photos")
本章小结
- 自动整理文件夹:识别文件类型、按分类移动文件
- 预览操作:查看将要执行的操作,避免误操作
- 回滚功能:支持撤销操作,不用担心整理错了
- 自定义规则:可以添加自己的分类规则
- 进阶功能:按日期整理照片
这个工具可以帮你每天节省30分钟整理文件的时间!下一章我们来批量处理Excel,再也不加班!
继续学下去,马上就能做实用项目了!