import osimport shutilimport datetimefrom pathlib import Path
# 文件类型分类字典self.file_categories = {'图片': ['.jpg', '.jpeg', '.png', '.gif', '.bmp', '.tiff', '.ico', '.webp', '.svg'],'视频': ['.mp4', '.avi', '.mov', '.wmv', '.flv', '.mkv', '.webm', '.m4v', '.mpg', '.mpeg'],'文档': ['.doc', '.docx', '.xls', '.xlsx', '.ppt', '.pptx', '.odt', '.ods', '.odp'],'压缩文件': ['.zip', '.rar', '.7z', '.tar', '.gz', '.bz2', '.xz', '.tgz'],'音乐': ['.mp3', '.wav', '.flac', '.aac', '.ogg', '.wma', '.m4a'],'文本': ['.txt', '.md', '.rtf', '.csv', '.json', '.xml', '.yaml', '.yml'],'PDF文件': ['.pdf'],'安装包': ['.exe', '.msi', '.dmg', '.pkg', '.deb', '.rpm', '.apk'],'电子书': ['.epub', '.mobi', '.azw3', '.fb2'],'脚本': ['.py', '.sh', '.bat', '.ps1', '.js', '.php', '.java', '.cpp', '.c', '.html', '.css']}
# 需要排除的文件格式self.excluded_extensions = ['.sys', '.dll', '.ini', '.cfg', '.config', '.log', '.tmp', '.temp','.db', '.sqlite', '.lock', '.pid', '.swp', '.swo', '.DS_Store']# 需要排除的特定文件名模式self.excluded_patterns = ['desktop.ini', 'thumbs.db', '.gitignore', '.gitattributes','package-lock.json', 'yarn.lock', 'requirements.txt']
def get_file_category(self, file_extension, filename):"""根据文件扩展名确定文件类别Args:file_extension (str): 文件扩展名filename (str): 文件名Returns:str: 文件类别,如果不匹配则返回 None"""# 检查是否在排除列表中if file_extension.lower() in self.excluded_extensions:return None# 检查是否匹配排除的文件名模式if filename.lower() in self.excluded_patterns:return None# 匹配文件类别for category, extensions in self.file_categories.items():if file_extension.lower() in extensions:return categoryreturn None
def organize_files(self):"""整理目标路径下的文件"""print(f"开始整理路径: {self.target_path}")self.log_entries.append(f"文件整理开始时间: {datetime.datetime.now()}")self.log_entries.append(f"目标路径: {self.target_path}")# 统计信息stats = {'total': 0,'moved': 0,'skipped': 0,'categories': {category: 0 for category in self.file_categories.keys()}}try:# 遍历目标路径下的所有文件for item in self.target_path.iterdir():if item.is_file(): # 只处理文件,不处理文件夹stats['total'] += 1filename = item.name# 获取文件类别category = self.get_file_category(file_extension, filename)if category:# 创建分类文件夹category_folder = self.target_path / categorycategory_folder.mkdir(exist_ok=True)# 构建目标文件路径destination = category_folder / filename# 处理同名文件if destination.exists():# 如果目标文件已存在,添加时间戳重命名timestamp = datetime.datetime.now().strftime('%Y%m%d_%H%M%S')name_without_ext = item.stemnew_filename = f"{name_without_ext}_{timestamp}{file_extension}"destination = category_folder / new_filenametry:# 移动文件shutil.move(str(item), str(destination))stats['moved'] += 1stats['categories'][category] += 1log_message = f"[移动] {filename} -> {category}/{destination.name}"self.log_entries.append(log_message)print(log_message)except Exception as e:error_message = f"[错误] 无法移动文件 {filename}: {str(e)}"self.log_entries.append(error_message)print(error_message)stats['skipped'] += 1else:# 不需要操作的文件reason = "系统/排除文件" if (file_extension.lower() in self.excluded_extensions orfilename.lower() in self.excluded_patterns) else "未知文件类型"log_message = f"[跳过] {filename} - 原因: {reason}"self.log_entries.append(log_message)print(log_message)stats['skipped'] += 1except Exception as e:error_message = f"整理过程中发生错误: {str(e)}"self.log_entries.append(error_message)print(error_message)# 添加统计信息到日志self.log_entries.append("-" * 50)self.log_entries.append("整理统计:")self.log_entries.append(f"总文件数: {stats['total']}")self.log_entries.append(f"已移动文件数: {stats['moved']}")self.log_entries.append(f"跳过文件数: {stats['skipped']}")self.log_entries.append("")self.log_entries.append("按类别统计:")for category, count in stats['categories'].items():if count > 0:self.log_entries.append(f" {category}: {count} 个文件")self.log_entries.append("")self.log_entries.append(f"文件整理结束时间: {datetime.datetime.now()}")# 保存日志文件self.save_log()print(f"\n整理完成! 日志已保存到: {self.log_file}")return stats
def save_log(self):"""保存操作日志到txt文件"""try:with open(self.log_file, 'w', encoding='utf-8') as f:for entry in self.log_entries:f.write(entry + '\n')print(f"日志文件已保存: {self.log_file}")except Exception as e:print(f"保存日志文件时出错: {str(e)}")
