Python批量重命名文件时os.rename出现覆盖问题如何解决?
修复方案
问题根源
当前代码执行os.rename前未校验目标文件是否存在,绝大多数系统下该API会直接覆盖已有文件,导致重命名冲突时数据丢失。
核心修复逻辑
- 重命名前预生成所有文件的新旧路径映射,提前排查冲突
- 冲突时自动生成带序号后缀的不重复文件名,避免覆盖
- 全部映射校验通过后再统一执行重命名操作,避免中途出错导致文件状态混乱
修复后完整代码
import os import subprocess suffixes = ['.pdf', '.epub', '.mobi'] def get_unique_path(target_path): """生成不重复的目标路径,冲突时加(1)(2)后缀""" if not os.path.exists(target_path): return target_path # 拆分路径、文件名、后缀 dir_name, full_name = os.path.split(target_path) name, ext = os.path.splitext(full_name) counter = 1 while True: new_name = f"{name} ({counter}){ext}" new_path = os.path.join(dir_name, new_name) if not os.path.exists(new_path): return new_path counter += 1 def change_fname(dir_name, part=' (z-lib.org)', action='remove'): fnames = os.listdir(dir_name) # 先收集所有重命名映射,避免边改边遍历出错 rename_map = [] for suffix in suffixes: fnames_suffix = [f for f in fnames if f.endswith(suffix)] for fname in fnames_suffix: print(f'{action} "{part}" into/from "{fname}"') new_name = None if action == 'remove' and fname.endswith(part+suffix): new_name = fname[:-len(suffix) - len(part)] + suffix print(f'fname is {fname}') elif action == 'insert': new_name = fname[:-len(suffix)] + part + suffix else: raise Exception(f'Unknown Action: {action}') print(f'预设新名称:{new_name}') old_file = os.path.join(dir_name, fname) new_file = os.path.join(dir_name, new_name) # 生成不重复的新路径 unique_new_file = get_unique_path(new_file) if unique_new_file != new_file: print(f'目标名称冲突,自动调整为:{os.path.basename(unique_new_file)}') rename_map.append((old_file, unique_new_file)) # 全部校验通过后统一执行重命名 for old_path, new_path in rename_map: os.rename(old_path, new_path) print("全部重命名操作完成") if __name__ == '__main__': dir_name = '/Users/ChrisHart/Downloads/test i love you daddy/' file_to_show = dir_name subprocess.call(["open", "-R", file_to_show]) try: change_fname(dir_name, part=' (z-lib.org)', action='remove') except Exception as ex: print(ex)
效果说明
你提到的冲突场景会按如下逻辑处理:
原有文件:
- file.pdf
- file (part).pdf
执行remove操作时,file (part).pdf预设新名称为file.pdf,检测到该文件已存在,自动调整为file (1).pdf,不会覆盖原有文件,最终两个文件都会保留。
内容的提问来源于stack exchange,提问作者ChrisHart
相关产品推荐
相关产品推荐

