python必背源代码批量重命名文件代码

小林子
小林子
发布时间:2026-11-13| 5人浏览过
原创

本文系统整理了Python批量重命名文件的必背核心源代码,涵盖数字对齐归档、前后缀提取、字符串替换、正则解析重组以及防止文件覆盖的两阶段安全重命名机制,提供完整可运行的工程级代码模板与注意事项。

一、批量重命名的核心底层与标准库选择

在 Python 语言中,处理文件重命名通常有两个标准库选择:传统的 os 模块以及现代面向对象的 pathlib 模块(Python 3.4+ 内置)。虽然 os.rename(src, dst) 在老旧代码中依然常见,但在批量处理场景下,pathlib.Path 具备显著优势。

使用 pathlib.Path 时,路径被视为具备语义的对象,提供了 .stem(无后缀的主文件名)、.suffix(文件扩展名,自带句点)以及 .parent(所在父目录)等属性。开发者无需手动调用 os.path.splitext() 进行复杂的字符串切片,大幅降低了因多重扩展名(如 .tar.gz)或无扩展名文件导致的切片错误。

对比维度 传统 os 模块 (os.rename) 现代 pathlib 模块 (Path.rename)
对象类型 纯文本字符串 (str) 面向对象的路径实体 (Path)
提取主文件名 os.path.splitext(os.path.basename(path))[0] path.stem(直观且语义清晰)
提取扩展名 os.path.splitext(path)[1] path.suffix(原生支持)
跨平台路径拼接 os.path.join(dir, new_name) path.parent / new_name(通过 / 运算符直观拼接)
存在性判断 os.path.exists(path) path.exists()

一个标准的批量重命名执行过程由四个紧密相连的阶段构成:扫描定位目标文件、解析与重塑名称、重名冲突检测、物理落盘改名。执行逻辑如下图所示:

python必背源代码批量重命名文件代码
图 1:批量重命名执行标准四步流程管线

无论后续重命名逻辑如何变动,这四个步骤是编写自动化脚本的骨架。接下来将展示三套最实用、值得记忆并直接复用的经典代码实现。

二、经典必背代码实现:三大核心重命名模式

1. 模式一:格式化序号递增与自动对齐补零

此场景最常用于整理散乱的图片、测试日志、报告扫描件或机器学习数据集。关键做法是使用 enumerate() 获取递增计数,并通过 Python 的格式化字符串语法 {idx:03d}(或 :04d)在数字前方自动对齐补零。如果不补零,系统在按文件名 ASCII 码排序时会出现 10.jpg 排在 2.jpg 前面的错位现象。

from pathlib import Path

def rename_sequential(folder_path: str, prefix: str = "file", ext_filter: str = ".jpg") -> None:
    """按递增序号对指定目录下的特定文件进行批量重命名"""
    target_dir = Path(folder_path)
    if not target_dir.is_dir():
        raise NotADirectoryError(f"目标路径不存在或不是文件夹: {target_dir}")

    # 筛选出属于普通文件且扩展名匹配的列表,建议提前排序保证顺序固定
    files = sorted([p for p in target_dir.iterdir() if p.is_file() and p.suffix.lower() == ext_filter.lower()])
    
    for idx, file_path in enumerate(files, start=1):
        # :03d 表示数字宽度为3,不足3位高位自动补零(如 001, 002, ...)
        new_filename = f"{prefix}_{idx:03d}{file_path.suffix.lower()}"
        new_path = file_path.parent / new_filename

        if not new_path.exists():
            file_path.rename(new_path)
            print(f"[OK] {file_path.name} -> {new_filename}")
        else:
            print(f"[SKIP] 目标名称已存在,跳过: {new_filename}")

# 执行示例(调用前请确认路径)
# rename_sequential(r"/Users/project/photos", prefix="vacation", ext_filter=".jpg")

代码重点说明:在排序时显式调用 sorted() 至关重要。因为操作系统在读取目录索引项时返回的次序并不保证稳定,先排序能确保每次执行都能按照原始名称的固定顺序重新编排。

2. 模式二:统一追加前后缀与关键词精准替换

在日常归档或团队协作中,经常需要为一批文件增加项目标识前缀(如 v1.0_、Final_),或者剔除下载文件自带的广告网站后缀。此时的核心原则是只操作文件名主干 path.stem,保留原有 path.suffix 不变。

python必背源代码批量重命名文件代码
图 2:pathlib 文件名属性解耦与目标路径装配机制
from pathlib import Path

def rename_replace_or_prefix(folder_path: str, add_prefix: str = "", add_suffix: str = "", 
                             old_str: str = "", new_str: str = "") -> None:
    """对主文件名进行前缀添加、后缀添加或特定关键词替换"""
    target_dir = Path(folder_path)

    for file_path in target_dir.iterdir():
        if not file_path.is_file():
            continue

        stem = file_path.stem  # 获取去除扩展名后的主文件名
        
        # 执行内容替换
        if old_str:
            stem = stem.replace(old_str, new_str)
            
        # 组装前后缀
        new_stem = f"{add_prefix}{stem}{add_suffix}"
        new_filename = f"{new_stem}{file_path.suffix}"
        new_path = file_path.parent / new_filename

        if file_path != new_path and not new_path.exists():
            file_path.rename(new_path)
            print(f"[OK] {file_path.name} -> {new_filename}")
避坑提醒:不要直接对完整文件名使用 replace

很多初学者直接写 file_name.replace("doc", "docx"),如果原文件名是 document_review.doc,会导致替换后变成 docxument_review.docx,不仅污染了主文件名,甚至误改了扩展名。务必分离 stem 与 suffix 分开处理。

3. 模式三:正则表达式高级捕获与模式重构

当文件命名格式复杂(例如含有拍摄时间、机身型号、版本标记等混合信息)且需要重排时,字符串的切片和简单替换就显得力不从心。此时引入 re 模块的捕获组(Capture Groups),可以精准提取所需字段并重新编排。

import re
from pathlib import Path

def rename_with_regex(folder_path: str, pattern: str, replacement: str) -> None:
    """
    使用正则表达式对主文件名进行模式匹配与重组
    示例 pattern: r"^(\d{4})-(\d{2})-(\d{2})_(.*)$"  (匹配 2024-05-18_report)
    示例 replacement: r"\g<4>_\g<1>\g<2>\g<3>"           (重组成 report_20240518)
    """
    target_dir = Path(folder_path)
    regex = re.compile(pattern)

    for file_path in target_dir.iterdir():
        if not file_path.is_file():
            continue

        # 仅对主文件名执行正则匹配与替换
        original_stem = file_path.stem
        if regex.search(original_stem):
            new_stem = regex.sub(replacement, original_stem)
            new_filename = f"{new_stem}{file_path.suffix}"
            new_path = file_path.parent / new_filename

            if not new_path.exists():
                file_path.rename(new_path)
                print(f"[REGEX-OK] {file_path.name} -> {new_filename}")
            else:
                print(f"[CONFLICT] {new_filename} 目标已存在,跳过")

三、工程级防御:防止文件覆盖与两阶段暂存机制

在本地开发或批量处理数万个真实文件时,最严重的事故是“意外文件覆盖导致数据永久损毁”。在许多 POSIX 系统中,若目标路径 new_path 已存在文件,直接调用系统底层 rename() 会直接将目标文件覆写并不产生任何警示。

1. 为什么直接线性重命名会产生碰撞与死锁?

设想一个经典场景:你想将 file_1.txt 改名为 file_2.txt,将 file_2.txt 改名为 file_3.txt。如果在循环中从前向后执行,当处理 file_1.txt 时,磁盘上的 file_2.txt 就会被覆盖;轮到原有的 file_2.txt 时,数据其实早已丢失。另一个更典型的死锁是两文件名称互换:A -> B 且 B -> A。

python必背源代码批量重命名文件代码
图 3:重名冲突防护与两阶段暂存原子重命名模型

2. 两阶段暂存重命名法(Two-Stage Safe Rename)

工业级可靠性的解决范式是引入两阶段暂存重命名法:

  1. 第一阶段(隔离暂存):先将所有待重命名文件重命名为全局唯一的临时名称(例如在文件名前拼接包含 uuid4() 或高精度时间戳的特殊前缀 __tmp_uuid_...)。这一阶段彻底释放了原有的文件名占位,消除了相互碰撞的可能。
  2. 第二阶段(最终装配):遍历第一阶段的暂存映射字典,将每个临时文件逐一重命名为真正的最终目标名称。
import uuid
from pathlib import Path
from typing import List, Tuple

def safe_two_stage_rename(rename_plan: List[Tuple[Path, Path]]) -> None:
    """
    两阶段安全批量重命名
    :param rename_plan: 二元组列表 [(源路径Path, 最终目标路径Path), ...]
    """
    # 0. 前置严格冲突检查:检查计划输出中是否存在重复目标
    destination_set = set()
    for _, dst in rename_plan:
        if dst in destination_set:
            raise ValueError(f"重命名计划内部存在冲突目标: {dst}")
        destination_set.add(dst)

    temp_mappings: List[Tuple[Path, Path]] = []
    
    # 阶段一:批量转换为临时中间文件名
    print("--- [阶段一] 开始转入唯一隔离中间态 ---")
    for src, final_dst in rename_plan:
        if not src.exists():
            print(f"[WARN] 源文件不存在,跳过: {src}")
            continue
        # 构造带有随机 UUID 标记的中间文件名
        temp_name = f"__tmp_{uuid.uuid4().hex[:8]}_{src.name}"
        temp_path = src.parent / temp_name
        src.rename(temp_path)
        temp_mappings.append((temp_path, final_dst))

    # 阶段二:从临时文件名转为最终目标名称
    print("--- [阶段二] 从中间态转入最终目标 ---")
    success_count = 0
    for temp_path, final_dst in temp_mappings:
        if final_dst.exists():
            # 此时若已存在,说明是外部现有未纳入计划的文件,报错拦截
            raise FileExistsError(f"目标路径已被外部文件占用: {final_dst}")
        temp_path.rename(final_dst)
        success_count += 1
        print(f"[SUCCESS] -> {final_dst.name}")

    print(f"安全重命名完成,共成功落盘 {success_count} 个文件。")

四、批量重命名前的代码演练(Dry-Run机制)与综合选型

在任何真实环境执行批量重命名脚本前,强烈建议加入 dry_run 参数。所谓 Dry-Run,即“模拟演练”:代码会照常遍历文件、计算新文件名并进行冲突检测,并在终端完整打印变更对照表,但完全不调用任何实际的落盘修改操作。只有在肉眼核验无误后,再开启真实执行开关。

python必背源代码批量重命名文件代码
图 4:Python 批量重命名核心代码范式选型矩阵与决策全景

开箱即用通用代码模板

以下提供一个集成 dry_run 试运行开关、进度提示、计数统计以及异常保护的工业级开箱即用模板,适合直接保存到项目工程中或作为命令行小工具调用:

import sys
from pathlib import Path

def batch_rename_tool(
    folder: str, 
    prefix: str = "", 
    suffix: str = "", 
    seq_start: int = 1, 
    digits: int = 3, 
    filter_ext: str = None, 
    dry_run: bool = True
) -> None:
    """
    综合通用批量重命名主函数
    :param folder: 目标文件夹路径
    :param prefix: 新文件名前缀
    :param suffix: 新文件名后缀(放在编号之后,扩展名之前)
    :param seq_start: 递增序号起始值
    :param digits: 序号位数补零(例如 3 表示 001~999)
    :param filter_ext: 限定扩展名,如 '.pdf',为 None 时处理所有文件
    :param dry_run: 演练模式标志位(默认为 True,不修改磁盘)
    """
    target_path = Path(folder)
    if not target_path.exists() or not target_path.is_dir():
        print(f"错误: 目标路径不存在或非文件夹: {folder}", file=sys.stderr)
        return

    # 检索待处理文件
    files = [f for f in target_path.iterdir() if f.is_file()]
    if filter_ext:
        files = [f for f in files if f.suffix.lower() == filter_ext.lower()]

    files.sort(key=lambda x: x.name)
    total_files = len(files)
    if total_files == 0:
        print("未找到匹配的文件,流程终止。")
        return

    print(f"=== 批量重命名任务启动 (模式: {'【模拟演练 DRY-RUN】' if dry_run else '【真实执行 LIVE】'}) ===")
    print(f"工作目录: {target_path.resolve()}")
    print(f"匹配文件总数: {total_files}
")

    planned_moves = []
    has_conflict = False

    for i, f in enumerate(files, start=seq_start):
        idx_str = str(i).zfill(digits)
        new_name = f"{prefix}{idx_str}{suffix}{f.suffix.lower()}"
        destination = f.parent / new_name

        # 检测重名风险
        conflict_tag = ""
        if destination.exists() and destination != f:
            conflict_tag = " [⚠ 冲突:目标文件已存在]"
            has_conflict = True

        print(f"  [{i}] {f.name}  --->  {new_name}{conflict_tag}")
        planned_moves.append((f, destination))

    if has_conflict:
        print("
[警告] 检测到目标名称冲突!为保障安全,请修正规则或改用两阶段暂存机制。")
        if not dry_run:
            print("任务中止:未对磁盘做任何修改。")
            return

    if dry_run:
        print("
提示: 以上仅为模拟预览输出。确认无误后,将 dry_run 设置为 False 即可实际执行重命名。")
    else:
        print("
开始执行实际落盘...")
        done_cnt = 0
        for src, dst in planned_moves:
            if src != dst:
                src.rename(dst)
                done_cnt += 1
        print(f"执行完毕!已成功重命名 {done_cnt} 个文件。")

# 实际调用示例:先演练预览,确认无误再将 dry_run 改为 False
if __name__ == "__main__":
    # batch_rename_tool(r"./my_data", prefix="doc_", seq_start=1, digits=3, filter_ext=".pdf", dry_run=True)
    pass

五、开发与运行注意事项

在编写和运行 Python 文件批处理脚本时,以下几个工程细节经常被忽略,但在实际生产场景中至关重要:

  • 操作系统大小写敏感性差异:在 Linux 系统下,Image.jpg 和 image.jpg 是两个不同的文件;而在 Windows 和 macOS(默认 APFS 不区分大小写配置)下,它们指向同一文件。如果仅仅想将文件名由大写改成小写(如 DOC.TXT 改为 doc.txt),在 Windows 上直接 rename 可能会抛出异常或被系统判定无变化,此时必须借助两阶段暂存法或临时中转名完成。
  • 特殊字符与转义保护:文件名中如果包含空格、方括号 []、圆括号 ()、特殊符号等,在控制台直接执行 shell 命令极易出错,但 Python 的 pathlib 在底层直接向系统内核传递 Unicode 字符串,天然规避了命令行转义注入的问题。
  • 文件占用与权限锁定:在 Windows 系统下,如果某个待重命名的文件正被 Excel、Word 或其他进程以独占方式打开,Python 会抛出 PermissionError: [WinError 32] 另一个程序正在使用此文件。在生产脚本中,应当使用 try...except PermissionError 包裹重命名调用,记录失败日志并允许重试。
相关专题:

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。