Python批量重命名文件:匹配多模式并仅保留匹配项
批量重命名文件脚本解决方案
需求说明
- 存在多行多词的模式列表,示例:
r'House', r'Big Tree', r'Word', - 遍历文件夹内文件名,匹配规则:
- 忽略大小写
- 忽略
-、_、,及其他特殊字符,支持多个连续分隔符 - 多词模式(如
Big Tree)需匹配所有分隔符组合形式(如__big_tree_、big,tree_等)
- 匹配到一个或多个模式时,仅保留模式原文和文件扩展名作为新文件名;未匹配的文件不修改
示例
原文件名:
__big_tree_and_5_more_house_and_1_more_drawn_by_a_n_name__f95c144ac5d5cf0a0baa24d6593cc699.jpgTable-Home-Word-7325313.jpegkiwi 40055619 virtual YouTube,Search EN, 100+ bookmarks 115480616_p0.png
预期输出文件名:
Big Tree House.jpgWord.jpegkiwi 40055619 virtual YouTube,Search EN, 100+ bookmarks 115480616_p0.png
现有代码问题
- 匹配逻辑未处理分隔符和多词模式的情况,无法正确匹配如
__big_tree_这类形式 - 使用临时文件夹中转,重启脚本时会导致文件重复问题
- 未处理大小写忽略的匹配需求
优化方案代码
步骤说明
- 模式转正则:将每个模式转换为支持任意分隔符的正则表达式,同时启用忽略大小写匹配
- 独立模式库:将模式存储在单独的
patterns.txt文件中,每行一个模式,方便维护大量模式 - 原地重命名:直接在原目录处理文件,避免临时文件夹带来的问题;自动处理文件名冲突,添加序号后缀
- 完整匹配逻辑:遍历所有模式,收集所有匹配的模式原文,拼接成新文件名
完整代码
import os import re def load_patterns(pattern_file): """从文件中加载模式列表""" with open(pattern_file, 'r', encoding='utf-8') as f: # 读取每行并去除首尾空白,跳过空行 patterns = [line.strip() for line in f if line.strip()] return patterns def pattern_to_regex(pattern): """将多词模式转换为支持任意分隔符的正则表达式""" # 把模式中的空格替换成匹配任意非单词字符(支持多个连续)的正则 regex_parts = re.split(r'\s+', pattern) regex_pattern = r'\W+'.join(re.escape(part) for part in regex_parts) # 启用忽略大小写,并且匹配整个词(避免部分匹配,比如Word不匹配Word2) return re.compile(regex_pattern, re.IGNORECASE) def get_matched_patterns(filename, patterns_regex_map): """获取文件名中匹配到的所有模式原文""" matched = set() # 用集合避免重复匹配同一模式 for pattern, regex in patterns_regex_map.items(): if regex.search(filename): matched.add(pattern) # 按原模式列表顺序排序(可选,保持匹配顺序一致) return sorted(matched, key=lambda x: list(patterns_regex_map.keys()).index(x)) def get_unique_filename(directory, base_name, extension): """生成不重复的文件名,处理冲突""" counter = 1 new_filename = f"{base_name}{extension}" new_filepath = os.path.join(directory, new_filename) while os.path.exists(new_filepath): new_filename = f"{base_name} {counter}{extension}" new_filepath = os.path.join(directory, new_filename) counter += 1 if counter > 9999: break # 防止无限循环 return new_filename def rename_files(directory, patterns): """批量重命名文件""" # 构建模式到正则的映射 patterns_regex_map = {pattern: pattern_to_regex(pattern) for pattern in patterns} for filename in os.listdir(directory): filepath = os.path.join(directory, filename) if not os.path.isfile(filepath): continue # 跳过文件夹 base, ext = os.path.splitext(filename) matched_patterns = get_matched_patterns(base, patterns_regex_map) if not matched_patterns: continue # 未匹配到任何模式,跳过 # 拼接匹配的模式原文作为新文件名主体 new_base = ' '.join(matched_patterns) new_filename = get_unique_filename(directory, new_base, ext) # 执行重命名 new_filepath = os.path.join(directory, new_filename) os.rename(filepath, new_filepath) print(f"重命名: {filename} -> {new_filename}") if __name__ == "__main__": # 配置 TARGET_DIR = "./" # 待处理目录 PATTERN_FILE = "patterns.txt" # 模式文件路径 # 加载模式 try: patterns = load_patterns(PATTERN_FILE) except FileNotFoundError: print(f"错误:未找到模式文件 {PATTERN_FILE}") exit(1) if not patterns: print("错误:模式文件为空") exit(1) # 执行重命名 rename_files(TARGET_DIR, patterns) print("重命名完成")
使用说明
- 创建
patterns.txt文件,每行一个模式,比如:House Big Tree Word - 将脚本放在待处理文件夹中,或者修改
TARGET_DIR为目标文件夹路径 - 运行脚本即可完成重命名
关键优化点
- 正则匹配逻辑:用
\W+匹配任意非单词字符(包括-、_、,等),支持连续分隔符;启用re.IGNORECASE忽略大小写 - 模式独立性:模式存储在外部文件,方便维护数千个模式,无需修改代码
- 无临时文件夹:直接原地重命名,避免文件重复问题
- 冲突处理:自动为重复文件名添加序号,避免覆盖
内容的提问来源于stack exchange,提问作者Nicetas
相关产品推荐
相关产品推荐

