Files
2026-10-07 11:07:00 +08:00

131 lines
5.0 KiB
Python

import os
import re
import argparse
from datetime import datetime
# ====================== 【配置区,不再写死目录】 ======================
LOG_FILE = "./rename_log.txt"
# 清洗规则
RULES = [
(r"^[A-Za-z] ", ""), #1.移除开头单个字母+空格
(r"\[.*?\]", ""), #2.移除英文方括号及内部内容
(r"【.*?】", ""), #3.移除中文【】及内部内容
(r"丨", ""), #清除汉字竖线 丨
(r"\b(2160p|1080p|720p|HDR|DV|DoVi|HEVC|x265|x264|DDP|AAC|Atmos|TrueHD|中英双语|双语字幕)\b", "", re.IGNORECASE),
(r"\.+", ""), #删除连续的点
(r"\s", ""), #删除全部空格
# 保留:汉字、半角英文、数字、半角 () . : + -
(r"[^\u4e00-\u9fa5a-zA-Z0-9().:+-]", ""),
]
ALLOW_EXT = {".mkv", ".mp4", ".mov", ".srt", ".ass", ".sub", ".strm",".flv",".avi",".wmv",".ts",".rmvb",".webm",".mp3",".flac",".aac",".wav",".ogg",".m4a",".wma",".alac",".rm",".iso"}
# ====================================================================
def clean_filename(name: str) -> str:
name_no_ext, ext = os.path.splitext(name)
# 全角转半角
def full2half(s):
result = []
for char in s:
code = ord(char)
if code == 12288:
char = chr(32)
elif 65281 <= code <= 65374:
char = chr(code - 65248)
result.append(char)
return "".join(result)
name_no_ext = full2half(name_no_ext)
for item in RULES:
if len(item) == 3:
pat, repl, flag = item
name_no_ext = re.sub(pat, repl, name_no_ext, flags=flag)
else:
pat, repl = item
name_no_ext = re.sub(pat, repl, name_no_ext)
name_no_ext = name_no_ext.strip()
return name_no_ext + ext
def write_log(msg: str):
now = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
line = f"[{now}] {msg}"
print(line)
with open(LOG_FILE, "a", encoding="utf-8") as f:
f.write(line + "\n")
f.flush()
def main():
parser = argparse.ArgumentParser(description="媒体文件名批量清洗重命名工具")
parser.add_argument("--dir", required=True, help="目标根目录路径")
parser.add_argument("--apply", action="store_true", help="加上此参数才执行真实重命名;默认仅预览DryRun")
args = parser.parse_args()
target_dir = args.dir
DRY_RUN = not args.apply
# 校验目录是否存在
if not os.path.isdir(target_dir):
print(f"错误:目录不存在 -> {target_dir}")
return
# 每次运行前清空日志文件
with open(LOG_FILE, "w", encoding="utf-8") as f:
f.flush()
write_log("===== 文件名+文件夹清洗(移除开头A 中文片名前缀) =====")
write_log(f"根目录:{target_dir}")
write_log(f"预览模式 DRY_RUN = {DRY_RUN}")
file_rename_list = []
dir_rename_list = []
total_scan_dirs = 0
total_all_files = 0 # 全部扫描到的文件(所有后缀)
total_media_files = 0 # 媒体文件(ALLOW_EXT后缀)
for root, dirs, files in os.walk(target_dir, topdown=False):
total_scan_dirs += 1
for fname in files:
total_all_files +=1
ext = os.path.splitext(fname)[1].lower()
if ext in ALLOW_EXT:
total_media_files += 1
new_name = clean_filename(fname)
if new_name != fname:
old_path = os.path.join(root, fname)
new_path = os.path.join(root, new_name)
file_rename_list.append((old_path, new_path))
write_log(f"待修改文件-> {fname} → {new_name}")
# 处理文件夹
for dname in dirs:
new_name = clean_filename(dname)
if new_name != dname:
old_path = os.path.join(root, dname)
new_path = os.path.join(root, new_name)
dir_rename_list.append((old_path, new_name))
write_log(f"待修改文件夹-> {dname} → {new_name}")
# ========== 执行阶段 ==========
if not DRY_RUN:
# 先文件
for old, new in file_rename_list:
try:
os.rename(old, new)
except Exception as e:
write_log(f"【文件重命名失败】{old} -> {new} | 错误:{e}")
# 后文件夹
for old, new in dir_rename_list:
try:
os.rename(old, new)
except Exception as e:
write_log(f"【文件夹重命名失败】{old} -> {new} | 错误:{e}")
# 最终汇总输出
write_log(f"任务完成,总扫描目录:{total_scan_dirs},待修改文件夹:{len(dir_rename_list)}")
write_log(f"总扫描文件:{total_all_files},媒体文件:{total_media_files},待修改文件:{len(file_rename_list)}")
write_log("============================================================")
if __name__ == "__main__":
main()