You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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)

效果说明

你提到的冲突场景会按如下逻辑处理:
原有文件:

  1. file.pdf
  2. file (part).pdf

执行remove操作时,file (part).pdf预设新名称为file.pdf,检测到该文件已存在,自动调整为file (1).pdf,不会覆盖原有文件,最终两个文件都会保留。

内容的提问来源于stack exchange,提问作者ChrisHart

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 00:39:03