如何用Python案例实现批量文件重命名?

wen python案例 13

本文目录导读:

如何用Python案例实现批量文件重命名?

  1. 方案一:基础批量重命名(添加前缀/后缀)
  2. 方案二:序列号重命名
  3. 方案三:替换文件名中的特定文本
  4. 方案四:高级批量重命名(正则表达式)
  5. 方案五:基于文件元数据重命名(照片示例)
  6. 方案六:完整封装的批量重命名工具类
  7. 使用建议

我来为您介绍几种批量文件重命名的Python实现方案,包含不同的应用场景。

基础批量重命名(添加前缀/后缀)

import os
import glob
def batch_rename_add_prefix_suffix(folder_path, prefix='', suffix='', file_ext='*'):
    """
    批量添加前缀或后缀
    :param folder_path: 文件夹路径
    :param prefix: 要添加的前缀
    :param suffix: 要添加的后缀(不含扩展名)
    :param file_ext: 文件扩展名,如'.txt','.jpg'
    """
    # 获取所有匹配的文件
    pattern = os.path.join(folder_path, f'*.{file_ext}' if file_ext != '*' else '*')
    files = glob.glob(pattern)
    for file_path in files:
        # 分离文件名和扩展名
        dir_name = os.path.dirname(file_path)
        file_name, ext = os.path.splitext(os.path.basename(file_path))
        # 构建新文件名
        new_name = f"{prefix}{file_name}{suffix}{ext}"
        new_path = os.path.join(dir_name, new_name)
        # 执行重命名
        os.rename(file_path, new_path)
        print(f"重命名: {os.path.basename(file_path)} -> {new_name}")
# 使用示例
batch_rename_add_prefix_suffix('./my_files', prefix='2024_', suffix='_new', file_ext='txt')

序列号重命名

import os
def batch_rename_sequential(folder_path, base_name='file', start_num=1, digits=3, file_ext=None):
    """
    批量重命名为序列号格式
    :param folder_path: 文件夹路径
    :param base_name: 基础文件名
    :param start_num: 起始编号
    :param digits: 编号位数
    :param file_ext: 指定文件扩展名(可选)
    """
    files = os.listdir(folder_path)
    # 过滤文件(排除文件夹)
    files = [f for f in files if os.path.isfile(os.path.join(folder_path, f))]
    # 如果指定了扩展名,进一步过滤
    if file_ext:
        files = [f for f in files if f.endswith(file_ext)]
    # 可选:按文件名排序
    files.sort()
    for i, old_name in enumerate(files):
        _, ext = os.path.splitext(old_name)
        new_name = f"{base_name}_{str(start_num + i).zfill(digits)}{ext}"
        old_path = os.path.join(folder_path, old_name)
        new_path = os.path.join(folder_path, new_name)
        os.rename(old_path, new_path)
        print(f"{old_name} -> {new_name}")
# 使用示例
batch_rename_sequential('./images', base_name='photo', start_num=1, digits=4, file_ext='.jpg')

替换文件名中的特定文本

import os
def batch_rename_replace_text(folder_path, old_text, new_text, file_ext=None):
    """
    批量替换文件名中的文本
    :param folder_path: 文件夹路径
    :param old_text: 要替换的文本
    :param new_text: 新文本
    :param file_ext: 指定文件扩展名(可选)
    """
    for file_name in os.listdir(folder_path):
        file_path = os.path.join(folder_path, file_name)
        # 跳过文件夹
        if not os.path.isfile(file_path):
            continue
        # 检查扩展名
        if file_ext and not file_name.endswith(file_ext):
            continue
        # 执行替换
        if old_text in file_name:
            new_name = file_name.replace(old_text, new_text)
            new_path = os.path.join(folder_path, new_name)
            os.rename(file_path, new_path)
            print(f"替换: {file_name} -> {new_name}")
# 使用示例
batch_rename_replace_text('./documents', old_text='_old', new_text='_new', file_ext='.pdf')

高级批量重命名(正则表达式)

import os
import re
def batch_rename_regex(folder_path, pattern, replacement, file_ext=None):
    """
    使用正则表达式批量重命名
    :param folder_path: 文件夹路径
    :param pattern: 正则表达式模式
    :param replacement: 替换字符串
    :param file_ext: 指定文件扩展名(可选)
    """
    for file_name in os.listdir(folder_path):
        file_path = os.path.join(folder_path, file_name)
        if not os.path.isfile(file_path):
            continue
        if file_ext and not file_name.endswith(file_ext):
            continue
        # 使用正则表达式替换
        new_name = re.sub(pattern, replacement, file_name)
        if new_name != file_name:
            new_path = os.path.join(folder_path, new_name)
            # 检查新文件名是否已存在
            if not os.path.exists(new_path):
                os.rename(file_path, new_path)
                print(f"正则重命名: {file_name} -> {new_name}")
            else:
                print(f"跳过: {file_name} -> {new_name} (文件已存在)")
# 使用示例:移除文件名中的数字
batch_rename_regex('./data', pattern=r'\d+', replacement='', file_ext='.txt')
# 使用示例:将下划线替换为连字符
batch_rename_regex('./files', pattern=r'_', replacement='-')

基于文件元数据重命名(照片示例)

import os
import datetime
from PIL import Image
from PIL.ExifTags import TAGS
def get_photo_date(file_path):
    """获取照片的拍摄日期"""
    try:
        image = Image.open(file_path)
        exifdata = image.getexif()
        for tag_id, value in exifdata.items():
            tag = TAGS.get(tag_id, tag_id)
            if tag == "DateTimeOriginal":
                return datetime.datetime.strptime(value, "%Y:%m:%d %H:%M:%S")
    except:
        # 如果无法获取EXIF信息,使用文件修改时间
        return datetime.datetime.fromtimestamp(os.path.getmtime(file_path))
    return None
def batch_rename_photos_by_date(folder_path):
    """
    使用照片拍摄日期重命名
    """
    photo_extensions = ['.jpg', '.jpeg', '.png', '.raw']
    for file_name in os.listdir(folder_path):
        file_path = os.path.join(folder_path, file_name)
        if not os.path.isfile(file_path):
            continue
        ext = os.path.splitext(file_name)[1].lower()
        if ext not in photo_extensions:
            continue
        # 获取拍摄日期
        photo_date = get_photo_date(file_path)
        if photo_date:
            new_name = f"{photo_date.strftime('%Y%m%d_%H%M%S')}{ext}"
            new_path = os.path.join(folder_path, new_name)
            os.rename(file_path, new_path)
            print(f"照片重命名: {file_name} -> {new_name}")
# 使用前需要安装:pip install Pillow
# batch_rename_photos_by_date('./photos')

完整封装的批量重命名工具类

import os
import shutil
from typing import List, Callable
class FileRenamer:
    """批量文件重命名工具类"""
    def __init__(self, folder_path: str):
        self.folder_path = folder_path
        self.backup_folder = None
    def get_files(self, pattern: str = None) -> List[str]:
        """获取文件列表"""
        files = []
        for f in os.listdir(self.folder_path):
            file_path = os.path.join(self.folder_path, f)
            if os.path.isfile(file_path):
                if pattern is None or f.endswith(pattern):
                    files.append(f)
        return sorted(files)
    def create_backup(self) -> str:
        """创建备份文件夹"""
        timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
        self.backup_folder = f"{self.folder_path}_backup_{timestamp}"
        shutil.copytree(self.folder_path, self.backup_folder)
        print(f"备份创建成功: {self.backup_folder}")
        return self.backup_folder
    def rename(self, rename_func: Callable[[str], str], preview: bool = True):
        """
        执行重命名操作
        :param rename_func: 重命名函数,接收原文件名,返回新文件名
        :param preview: 是否预览(不实际执行)
        """
        files = self.get_files()
        operations = []
        for file_name in files:
            new_name = rename_func(file_name)
            if new_name and new_name != file_name:
                operations.append((file_name, new_name))
        if preview:
            print("=== 预览重命名操作 ===")
            for old, new in operations:
                print(f"{old} -> {new}")
            print(f"共 {len(operations)} 个文件将被重命名")
        else:
            # 创建备份
            self.create_backup()
            # 执行重命名
            for old_name, new_name in operations:
                old_path = os.path.join(self.folder_path, old_name)
                new_path = os.path.join(self.folder_path, new_name)
                if not os.path.exists(new_path):
                    os.rename(old_path, new_path)
                    print(f"重命名: {old_name} -> {new_name}")
                else:
                    print(f"跳过: {new_name} 已存在")
# 使用示例
def main():
    renamer = FileRenamer('./my_files')
    # 定义重命名规则
    def add_date_prefix(filename):
        from datetime import datetime
        date_str = datetime.now().strftime("%Y%m%d")
        return f"{date_str}_{filename}"
    # 预览
    renamer.rename(add_date_prefix, preview=True)
    # 实际执行
    # renamer.rename(add_date_prefix, preview=False)
if __name__ == "__main__":
    main()

使用建议

  1. 先备份:在批量重命名前,建议先备份重要文件
  2. 先预览:使用preview=True预览效果后再执行
  3. 测试小范围:先用少量文件测试
  4. 正则表达式:复杂的文本替换可使用正则表达式

这些方法涵盖了大部分批量重命名需求,您可以根据具体场景选择合适的方案。

抱歉,评论功能暂时关闭!