使用 Python 批量按指定顺序重命名文件夹

🧰 使用 Python 批量按指定顺序重命名文件夹

在日常工作中,常常需要整理一批文件夹,并按特定顺序重命名,例如给文件夹添加序号前缀,方便浏览或汇报。这篇文章介绍一个实用的 Python 脚本,它可以根据一个指定的列表文件,批量为文件夹添加序号前缀。

🗂️ 场景示例

假设你有一批单位名称的文件夹:

盐池县/
├── 吴忠市公安局
├── 盐池县民政局
├── 盐池县农业农村局
└── ...

你希望根据一个列表文件 list.txt 中的顺序为这些文件夹重命名,例如:

吴忠市公安局
盐池县民政局
盐池县农业农村局

执行脚本后,它们将变成:

01_吴忠市公安局
02_盐池县民政局
03_盐池县农业农村局

📄 list.txt 文件格式

吴忠市公安局
盐池县民政局
盐池县农业农村局

每行一个文件夹名称,表示重命名后的顺序。

🧑‍💻 Python 脚本

以下是完整脚本,保存为 rename_folders.py

import os
import shutil

def read_order_from_list(file_path):
    with open(file_path, 'r', encoding='gbk') as f:
        return [line.strip() for line in f if line.strip()]

def rename_top_folders_by_order(order_list, base_path='.'):
    for index, folder_name in enumerate(order_list, start=1):
        old_path = os.path.join(base_path, folder_name)
        if not os.path.isdir(old_path):
            print(f'❌ 文件夹不存在: {folder_name}')
            continue

        # 如果已经是 01_名称 的形式,尝试还原
        parts = folder_name.split('_', 1)
        if len(parts) == 2 and parts[0].isdigit():
            folder_name = parts[1]
            old_path = os.path.join(base_path, folder_name)

        prefix = f'{index:02d}_'
        new_name = prefix + folder_name
        new_path = os.path.join(base_path, new_name)

        if os.path.exists(new_path):
            print(f'⚠️ 已存在: {new_name},跳过')
            continue

        shutil.move(old_path, new_path)
        print(f'✅ 重命名: {folder_name}{new_name}')

if __name__ == '__main__':
    order_file = './盐池县/list.txt'
    base_dir = './盐池县/'
    folder_order = read_order_from_list(order_file)
    rename_top_folders_by_order(folder_order, base_dir)

📝 使用说明

  1. 在目标目录(如 ./盐池县/)中创建或放置 list.txt
  2. 确保里面的文件夹名称与实际目录匹配。
  3. 运行脚本:
python rename_folders.py

即可自动重命名为 01_单位名称 的格式。

💡 提示与注意事项

  • 文件编码设为 GBK 是因为部分 Windows 系统中的中文文件默认是该编码,如果你使用的是 UTF-8,可将 encoding='gbk' 改为 encoding='utf-8'
  • 脚本会自动跳过不存在的文件夹,并提示警告信息。
  • 如果目标文件夹名称已存在(如手动提前命名),也会跳过以避免覆盖。

这段小脚本虽然简单,但在大量文档或单位材料管理中非常实用。如果你也有类似的场景,不妨试试看,并根据需要进行定制。

🧡 有用就点个赞或留言交流吧!


如果你需要将这篇文章发布到 优快云、掘金或博客园,我可以为你加上适合的平台标签与格式。需要吗?

<think>我们参考上述引用内容,特别是引用[2]和引用[4]中的代码示例,来编写一个批量重命名文件的Python脚本。 用户需求:使用Python指定文件夹内的文件进行批量重命名。 我们将设计一个函数,它接受一个文件夹路径,然后按照用户指定的规则重命名文件。 由于用户没有指定具体的重命名规则,我们可以提供几种常见的重命名方式: 1. 按顺序编号:例如将文件重命名为1.jpg, 2.jpg, ... 2. 删除文件名中的特定子字符串。 3. 替换文件名中的部分字符串。 4. 在文件名中添加前缀或后缀。 但是,用户没有给出具体规则,因此我们可以先实现一个通用的框架,并允许用户自定义重命名规则。 考虑到用户可能需要不同的规则,我们可以设计一个回调函数(或使用lambda表达式)来让用户指定如何生成新文件名。 然而,为了简单起见,我们先实现一个按顺序编号的重命名,并允许用户通过修改代码来定制规则。 参考引用[4]中的代码,它按顺序将所有的.jpg文件重命名为0.jpg, 1.jpg, ... 但是,用户可能想要重命名所有文件,而不仅仅是图片,并且可能想要保留原扩展名。 因此,我们可以设计如下: 函数:batch_rename(folder_path, rule_function) - folder_path: 文件夹路径 - rule_function: 一个函数,它接受原文件名和当前索引(可选),返回新文件名(不带路径) 但是,为了更灵活,我们也可以让用户选择是否使用索引。 然而,用户可能不需要编程接口,而是直接修改脚本。因此,我们可以先写一个简单的版本,然后让用户根据需要修改。 下面是一个基础版本,它按顺序编号,并保留原扩展名: 步骤: 1. 获取文件夹中所有文件的列表(不包括子文件夹)。 2. 遍历每个文件,获取文件名和扩展名。 3. 按照顺序生成新的文件名(例如:1,2,3...),并保持扩展名不变。 4. 使用os.rename进行重命名。 但是,为了避免覆盖,我们需要确保新文件名不会与已有的文件名冲突。我们可以先将要重命名的文件列出来,然后按顺序重命名。 然而,按顺序重命名时,如果直接使用数字,可能会覆盖掉后面的文件。因此,我们可以先收集所有文件,然后按原文件名排序(或按修改时间等),然后再重命名。 另外,我们也可以先复制到一个临时文件夹,但这样需要额外空间。所以,我们可以先收集所有文件,然后按照一定的顺序(比如按文件名排序)进行重命名,然后从0开始编号。 但是,在重命名过程中,如果目标文件名已经存在,就会出错。为了避免这种情况,我们可以先使用临时文件名(例如在数字前加一个前缀),最后再统一去掉前缀?这样比较复杂。 一个简单的方法是:先全部重命名为临时文件名(比如在原文件名前加一个前缀),然后再重命名为目标文件名。但这样需要两次遍历。 另一种方法:我们可以先按倒序重命名(这样就不会覆盖),但这样需要知道新文件名和旧文件名的关系。 考虑到简单性,我们可以先按顺序生成新文件名,然后先重命名到中间文件名(比如在原文件名前加一个临时前缀),然后再重命名为目标文件名。但这样两次遍历。 或者,我们可以先创建一个新的临时文件夹,将文件移动过去并重命名,然后再移动回来?这样更安全,但需要额外的复制操作。 实际上,如果我们是按顺序编号,并且新文件名和旧文件名完全不同(全是数字),那么只要旧文件名不是数字,就不会冲突。但是,如果文件夹中已经存在数字命名的文件,可能会冲突。 因此,我们采用一个安全的方法:先给所有文件重命名为一个临时名称(例如:在原文件名前加一个随机字符串或固定前缀如"temp_"),然后再将这些临时名称的文件重命名为目标文件名。 但是,这样需要两次遍历,而且如果文件很多,效率会低。 考虑到用户可能只需要简单的重命名,我们可以先按原文件名的顺序进行编号,这样如果原文件名不是数字,那么就不会覆盖。但是,如果原文件名就是数字,且顺序和编号顺序不一致,就可能覆盖。 所以,我们决定:先按原文件名的排序(比如按名称升序)来生成一个列表,然后按这个顺序重命名。但是,在重命名时,我们使用一个临时文件名(例如:先重命名为"temp_原文件名"),然后再重命名为目标文件名。这样需要两次重命名。 为了效率,我们也可以只遍历一次,但使用一个不会冲突的临时文件名。我们可以这样: 第一次遍历:将每个文件重命名为一个临时文件名(例如:在文件名前加一个唯一的前缀,比如索引号加一个下划线,但这样还是可能冲突?) 实际上,我们可以使用一个临时文件夹来存放,但这样需要移动文件。 考虑到简单性,我们采用两次遍历: 第一次:将原文件重命名为一个临时文件名(例如:在文件名前加一个固定的前缀,如"temp_" + 原文件名) 第二次:将临时文件名重命名为目标文件名(按顺序编号) 但是,这样如果用户只运行一次,那么会留下很多临时文件,而且如果中断,文件会处于临时状态。 因此,我们换一种思路:先收集所有文件,然后按照排序后的顺序,依次重命名为一个中间名称(比如:一个GUID或者时间戳?),但这样太复杂。 实际上,我们可以利用操作系统的重命名机制:只要目标文件不存在,就可以直接重命名。所以,我们可以先按排序后的文件列表,然后按顺序生成新文件名,然后检查新文件名是否存在。如果不存在,就直接重命名;如果存在,就先重命名为一个临时名称(比如在文件名前加一个随机字符串),然后再重命名为目标文件名。 这样逻辑复杂,代码量大。 考虑到用户可能只是少量文件,而且文件名原本没有规律,我们可以采用一个简单的方法:按原文件名的某种排序(比如按名称升序)后,从0开始编号,然后按顺序重命名。这样,如果新文件名和旧文件名不同,且新文件名之前不存在,那么就不会覆盖。但是,如果新文件名已经存在(比如文件夹中已经有一个0.jpg),那么就会覆盖。 因此,我们要求用户确保目标文件名不会与已有文件冲突。或者,我们可以先检查目标文件名是否存在,如果存在就跳过或报错。 但是,批量重命名通常是为了统一格式,所以目标文件名应该是全新的,不会重复。 所以,我们这样设计: 1. 获取文件夹中所有文件的列表(不包括文件夹)。 2. 对文件列表进行排序(比如按名称、按修改时间等,这里我们按名称排序)。 3. 遍历排序后的文件列表,对每个文件: old_path = os.path.join(folder_path, old_name) 获取扩展名:ext = os.path.splitext(old_name)[1] 新文件名 = f"{index}{ext}" # 这里index从0开始,也可以从1开始,用户可以修改 new_path = os.path.join(folder_path, new_name) 如果new_path已经存在,则报错(或跳过,或自动生成一个不重复的名字,比如在后面加(1)) 否则,重命名。 但是,如果用户希望保留原文件名的部分内容,或者添加前缀后缀,那么我们需要提供更灵活的方式。 因此,我们设计一个规则函数,由用户自定义。在规则函数中,用户可以根据原文件名和索引生成新文件名。 下面我们写一个函数,它接受文件夹路径和一个规则函数。规则函数签名为:rule(old_name, index) -> new_name(不带路径) 然后我们遍历文件,应用规则函数,然后重命名。 但是,为了避免冲突,我们可以在规则函数中要求用户保证新文件名不重复?或者我们在函数内部检查新文件名是否存在,如果存在则自动在名字后面加上序号(比如如果新文件名存在,则尝试新文件名_1,再存在则新文件名_2,直到不重复)。 考虑到用户可能希望完全控制,我们也可以不处理冲突,直接报错。 我们先写一个基础版本,不处理冲突,由用户确保规则函数返回的文件名不重复。 代码结构: def batch_rename(folder_path, rule_func): files = [f for f in os.listdir(folder_path) if os.path.isfile(os.path.join(folder_path, f))] # 排序,以便顺序编号 files.sort() for index, filename in enumerate(files): # 获取扩展名 base, ext = os.path.splitext(filename) new_name = rule_func(filename, index, base, ext) # 这里我们传递原文件名、索引、原基本名和扩展名 # 如果规则函数返回的新文件名没有包含扩展名,我们可以加上扩展名?或者规则函数自己处理扩展名 # 这里我们假设规则函数返回的是完整文件名(包括扩展名),这样更灵活,因为用户可能想改变扩展名。 old_file = os.path.join(folder_path, filename) new_file = os.path.join(folder_path, new_name) try: os.rename(old_file, new_file) print(f"重命名: {filename} -> {new_name}") except Exception as e: print(f"重命名 {filename} 失败: {str(e)}") 然后,用户需要自己定义规则函数。例如,按顺序编号的规则函数可以这样写: def sequential_rule(old_name, index, base, ext): return f"{index+1}{ext}" # 从1开始编号,保留原扩展名 但是,用户可能不想改变文件名的基本部分,只想添加前缀或后缀。例如: def add_prefix_rule(old_name, index, base, ext): return f"prefix_{base}{ext}" 或者删除特定字符串: def remove_substring_rule(old_name, index, base, ext): # 删除base中的特定子字符串,比如"temp_" new_base = base.replace("temp_", "") return f"{new_base}{ext}" 这样,用户就可以自定义规则。 但是,用户可能希望不修改代码就能使用,所以我们可以提供几个预设的规则,通过参数选择。 不过,由于用户问题中没有指定具体规则,我们先提供一个按顺序编号的示例,并允许用户修改规则函数。 下面我们写一个完整的示例,并包含一个按顺序编号的规则。 注意:为了避免重名冲突,我们在重命名之前检查新文件是否存在,如果存在则报错并跳过。 改进代码: def batch_rename(folder_path, rule_func): files = [f for f in os.listdir(folder_path) if os.path.isfile(os.path.join(folder_path, f))] files.sort() # 按文件名排序 for index, filename in enumerate(files): old_path = os.path.join(folder_path, filename) # 如果old_path不是文件,跳过(但我们已经过滤了) base, ext = os.path.splitext(filename) new_name = rule_func(filename, index, base, ext) new_path = os.path.join(folder_path, new_name) if os.path.exists(new_path): print(f"警告:目标文件 {new_name} 已存在,跳过重命名 {filename}") continue try: os.rename(old_path, new_path) print(f"重命名: {filename} -> {new_name}") except Exception as e: print(f"重命名 {filename} 失败: {str(e)}") 然后,我们定义规则函数,并调用。 但是,用户可能不想定义函数,所以我们也可以直接在调用时用lambda表达式。 示例:按顺序编号(从1开始,保留扩展名) rule = lambda old_name, index, base, ext: f"{index+1}{ext}" 然后调用:batch_rename(r"E:\your_folder", rule) 另外,用户可能希望保留原文件名的部分,比如引用[2]中只保留第一个下划线之前的部分。 我们可以这样定义规则: rule = lambda old_name, index, base, ext: base.split('_')[0] + ext 但是,注意:原文件名可能包含多个扩展名?所以使用os.path.splitext已经分离了最后一个扩展名。 因此,我们这样写是安全的。 下面我们给出一个完整的脚本示例,用户只需修改folder_path和rule_func即可。 注意:在重命名过程中,如果规则函数返回的新文件名重复,那么后面的文件会跳过。所以用户要确保规则函数返回的名字不重复。 另外,我们也可以提供一种更安全的模式:先将要重命名的文件复制到另一个文件夹?但这样不是重命名而是备份了。所以不采用。 现在,我们写一个完整的示例代码,并加上详细的注释。 注意:由于重命名操作不可逆,建议用户先备份文件。 代码示例:</think>以下是一个使用 Python 批量重命名文件夹内文件的完整解决方案,结合了多种常见需求场景的实现方法: ### 基础批量重命名脚本 ```python import os def batch_rename(folder_path, prefix="", suffix="", start_num=1): """ 批量重命名文件夹内的所有文件(保留原扩展名) 参数: folder_path: 文件夹路径(建议使用原始字符串 r"E:\your\folder") prefix: 文件名前缀(可选) suffix: 文件名后缀(可选) start_num: 起始编号(默认为1) """ # 获取文件列表(排除子文件夹) files = [f for f in os.listdir(folder_path) if os.path.isfile(os.path.join(folder_path, f))] # 按文件名排序 files.sort() for i, filename in enumerate(files, start=start_num): # 分离文件名和扩展名 name, ext = os.path.splitext(filename) # 构建新文件名(格式:前缀+编号+后缀+扩展名) new_name = f"{prefix}{i}{suffix}{ext}" # 构建完整路径 old_path = os.path.join(folder_path, filename) new_path = os.path.join(folder_path, new_name) # 执行重命名 os.rename(old_path, new_path) print(f"重命名: {filename} -> {new_name}") # 使用示例 if __name__ == "__main__": folder = r"E:\your\folder\path" # 替换为你的文件夹路径 batch_rename(folder, prefix="IMG_", suffix="_backup", start_num=1) ``` ### 常见场景扩展功能 #### 1. 按特定规则重命名(保留部分字符) ```python def rename_with_rule(folder_path, separator="_", keep_segments=1): """ 按分隔符规则重命名(如保留文件名中第一个下划线前的部分) 参数: separator: 分隔符(默认下划线) keep_segments: 保留的分段数量 """ for filename in os.listdir(folder_path): if os.path.isfile(os.path.join(folder_path, filename)): # 分离文件名和扩展名 name, ext = os.path.splitext(filename) # 按规则处理文件名 parts = name.split(separator) new_name = separator.join(parts[:keep_segments]) + ext # 执行重命名 old_path = os.path.join(folder_path, filename) new_path = os.path.join(folder_path, new_name) os.rename(old_path, new_path) ``` #### 2. 添加序号补零(001, 002...) ```python def rename_with_zeropad(folder_path, prefix="", digits=3): """ 添加补零序号(如 001.jpg, 002.jpg) 参数: digits: 序号位数(默认3位) """ files = [f for f in os.listdir(folder_path) if os.path.isfile(os.path.join(folder_path, f))] files.sort() for i, filename in enumerate(files, 1): _, ext = os.path.splitext(filename) new_name = f"{prefix}{i:0{digits}d}{ext}" old_path = os.path.join(folder_path, filename) new_path = os.path.join(folder_path, new_name) os.rename(old_path, new_path) ``` #### 3. 替换/删除特定字符串 ```python def replace_in_filename(folder_path, old_str, new_str=""): """ 替换或删除文件名中的特定字符串 参数: old_str: 需要替换的字符串 new_str: 替换后的字符串(留空则删除) """ for filename in os.listdir(folder_path): if os.path.isfile(os.path.join(folder_path, filename)): new_name = filename.replace(old_str, new_str) if new_name != filename: # 避免无意义重命名 old_path = os.path.join(folder_path, filename) new_path = os.path.join(folder_path, new_name) os.rename(old_path, new_path) ``` ### 使用注意事项 1. **路径格式**:建议使用原始字符串(如 `r"E:\photos"`)避免转义问题 2. **文件备份**:操作前建议复制文件夹进行测试 3. **排序控制**: - 添加 `files.sort(key=os.path.getmtime)` 可按修改时间排序 - 添加 `files.sort(key=os.path.getsize)` 可按文件大小排序 4. **过滤文件类型**: ```python # 只处理图片文件 files = [f for f in os.listdir(folder_path) if f.lower().endswith(('.png', '.jpg', '.jpeg'))] ``` ### 完整应用示例 ```python import os from datetime import datetime def smart_rename(folder_path): """智能重命名:日期前缀+序号+原文件名关键词""" today = datetime.now().strftime("%Y%m%d") files = [f for f in os.listdir(folder_path) if os.path.isfile(os.path.join(folder_path, f))] for i, filename in enumerate(files, 1): # 获取文件名关键词(第一个下划线前的部分) name_key = filename.split('_')[0] if '_' in filename else os.path.splitext(filename)[0] # 保留原扩展名 _, ext = os.path.splitext(filename) # 构建新文件名 new_name = f"{today}_{i:03d}_{name_key}{ext}" # 执行重命名 os.rename( os.path.join(folder_path, filename), os.path.join(folder_path, new_name) ) print(f"Renamed: {filename} → {new_name}") # 使用示例 if __name__ == "__main__": smart_rename(r"E:\photo_archive") ``` ### 常见问题解决 1. **权限错误**:确保文件未被其他程序占用 2. **文件名冲突**:脚本会自动跳过已存在的目标文件名 3. **特殊字符处理**:添加异常处理 ```python try: os.rename(old_path, new_path) except OSError as e: print(f"Error renaming {filename}: {str(e)}") ``` ### 安全建议 1. 首次使用前在测试文件夹中验证 2. 添加干运行模式(只显示不执行): ```python def dry_run(folder_path): for filename in os.listdir(folder_path): # ...计算新文件名... print(f"[Dry Run] {filename} → {new_name}") # 不执行实际重命名 ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

IT小辉同学

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值