我为什么写这个脚本
在日常工作和影音文件整理中,我经常遇到这样的困扰:数百个文件需要按照统一格式重命名,例如:
DVWA-CSRF漏洞详解-part1.mp4
DVWA_CSRF_02.avi
第三讲 csrf.mp4
...
传统解决方案存在三个痛点:
- 手动命名效率低下,容易出错
- 现有工具难以智能识别内容特征
- 需要保持编号连续性和格式统一
为此,我开发了这个结合深度学习和规则引擎的智能重命名脚本,实现:
• AI智能理解文件内容主题
• 自动识别多种编号格式(SXXEYY、连续数字等)
• 批量处理与冲突解决的一站式方案
Prompt设计艺术
系统级提示词
system_prompt = """您需要帮助用户批量重命名文件,请遵守以下规则:
1. 只需返回文件名主体(不要带扩展名)
2. 命名格式:[主题]_[编号]
3. 编号规则:
- 优先识别SXXEYY格式(如S01E03)
- 其次提取两位以上连续数字
- 最后使用顺序编号
4. 保持编号格式一致性"""
用户提示工程
user_prompt = f"""请为以下文件生成新名称(不要带扩展名):
主题:{theme}
文件列表:
{file_list}
通过结构化输入提升AI理解准确率
输出控制策略
pattern = re.compile(r'\d+\.\s*(.+)$', re.MULTILINE)
matches = pattern.findall(generated)
使用严格的正则表达式确保输出格式合规
完整实现代码
import re
import requests
from pathlib import Path
from typing import List, Dict
class SessionRenamer:
def __init__(self, api_key: str):
self.api_key = api_key
self.api_url = "https://api.deepseek.com/v1/chat/completions"
self.session_messages = []
self._init_session()
def _init_session(self):
"""初始化对话上下文"""
system_prompt = """您需要帮助用户批量重命名文件,请遵守以下规则:
1. 只需返回文件名主体(不要带扩展名)
2. 命名格式:[主题]_[编号]
3. 编号规则:
- 优先识别SXXEYY格式(如S01E03)
- 其次提取两位以上连续数字
- 最后使用顺序编号
4. 保持编号格式一致性"""
self.session_messages = [{
"role": "system",
"content": system_prompt
}]
def generate_names(self, filenames: List[str], theme: str) -> Dict[str, str]:
"""生成新文件名主体(不含扩展名)"""
file_list = "\n".join([f"{i + 1}. {Path(name).stem}" for i, name in enumerate(filenames)])
user_prompt = f"""请为以下文件生成新名称(不要带扩展名):
主题:{theme}
文件列表:
{file_list}
请按以下格式返回:
1. 新名称1
2. 新名称2
..."""
self.session_messages.append({"role": "user", "content": user_prompt})
try:
response = requests.post(
self.api_url,
headers={"Authorization": f"Bearer {self.api_key}"},
json={
"model": "deepseek-chat",
"messages": self.session_messages,
"temperature": 0.2,
},
timeout=20
).json()
generated_text = response['choices'][0]['message']['content']
return self._parse_output(filenames, generated_text)
except Exception as e:
print(f"API调用失败: {str(e)}")
return {}
@staticmethod
def _parse_output(originals: List[str], generated: str) -> Dict[str, str]:
"""解析输出并保留扩展名"""
pattern = re.compile(r'\d+\.\s*(.+)$', re.MULTILINE)
matches = pattern.findall(generated)
mapping = {}
for i, original in enumerate(originals):
original_path = Path(original)
# 保留原始扩展名
new_stem = matches[i] if i < len(matches) else original_path.stem
mapping[original] = f"{new_stem}{original_path.suffix}"
return mapping
class BatchRenamer:
def __init__(self, api_key: str):
self.api_key = api_key
self.backup_num = 0
self.episode_re = re.compile(r'(S\d+E\d+)', re.IGNORECASE)
self.number_re = re.compile(r'\d{2,}')
self.auto_mode = False
def process_folder(self, folder_path: str, theme: str):
files = [f for f in Path(folder_path).iterdir() if f.is_file()]
print(f"找到 {len(files)} 个文件")
# 生成新名称映射
renamer = SessionRenamer(self.api_key)
originals = [f.name for f in files]
name_mapping = renamer.generate_names(originals, theme)
# 应用重命名
for filepath in files:
new_name = name_mapping.get(filepath.name, None)
# 备用方案
if not new_name:
new_name = self._generate_fallback(filepath, theme)
new_path = self._resolve_conflicts(filepath.parent / new_name)
print(f"\n原文件: {filepath.name}")
print(f"新名称: {new_path.name}")
if self._get_confirmation():
filepath.rename(new_path)
print("✓ 已重命名")
def _generate_fallback(self, filepath: Path, theme: str) -> str:
"""备用命名方案"""
# 提取剧集编号
if match := self.episode_re.search(filepath.name):
return f"{theme}_{match.group(1)}{filepath.suffix}"
# 提取数字编号
if match := self.number_re.search(filepath.name):
return f"{theme}_{match.group()}{filepath.suffix}"
# 顺序编号
self.backup_num += 1
return f"{theme}_{self.backup_num:02d}{filepath.suffix}"
@staticmethod
def _resolve_conflicts(path: Path) -> Path:
"""处理文件名冲突"""
counter = 1
while path.exists():
new_stem = f"{path.stem}_{counter}"
path = path.with_name(f"{new_stem}{path.suffix}")
counter += 1
return path
def _get_confirmation(self) -> bool:
if self.auto_mode:
return True
resp = input("确认?(y/n/a/q): ").lower()
if resp == 'a':
self.auto_mode = True
return True
if resp == 'q': exit()
return resp == 'y'
if __name__ == "__main__":
API_KEY = "你的APIKEY"
TARGET_FOLDER = r"文件夹地址"
renamer = BatchRenamer(API_KEY)
renamer.process_folder(
folder_path=TARGET_FOLDER,
theme=input("请输入统一主题名称: ").strip()
)