使用Python的shutil.move重命名文件时触发FileNotFoundError问题
文件名补全脚本的FileNotFoundError问题解决
我正在学习《Automate the Boring Stuff》第10章,其中一项任务要求补全缺失序号的文件名(例如将capitalsquiz1、capitalsquiz3这类不连续的文件名重命名为连续序号)。编写代码后,注释shutil.move仅用print测试时,程序逻辑符合预期,但启用shutil.move后触发了FileNotFoundError。
我的代码
def fill_gap(folder): print(f'in {folder}') #create regex to find numbered filenames num = re.compile(r'^(.*?)((\d)?(\d)?(\d))') order =[] out = [] #go through all the files in the folder for oldfile in os.listdir(folder): mo = num.search(oldfile) if mo == None: continue order.append(mo.group(2)) order.sort(key = int) for i in range(len(order)): order[i] = mo.group(1) + order[i] out.append(mo.group(1)+str(i+1)) print(order) print(out) for i in range(len(order)): main = os.path.abspath(folder) old = os.path.join(main,order[i]) order[i] = out[i] new = os.path.join(main, order[i]) print(os.path.basename(old)) print(os.path.basename(new)) print (f'renaming "{old}" to "{new}"...') #shutil.move(old, new) fill_gap(r'C:\\Users\Andrei\pyject\rand_quiz')
报错信息
Traceback (most recent call last): File "C:\Program Files\Python311\Lib\shutil.py", line 825, in move os.rename(src, real_dst) FileNotFoundError: [WinError 2] The system cannot find the file specified: 'C:\\Users\\Andrei\\pyject\\rand_quiz\\capitalsquiz1' -> 'C:\\Users\\Andrei\\pyject\\rand_quiz\\capitalsquiz1' During handling of the above exception, another exception occurred: Traceback (most recent call last): File "C:\Users\Andrei\pyject\fill_gap_in_name.py", line 53, in <module> fill_gap(r'C:\\Users\Andrei\pyject\rand_quiz') File "C:\Users\Andrei\pyject\fill_gap_in_name.py", line 48, in fill_gap shutil.move(old, new) File "C:\Program Files\Python311\Lib\shutil.py", line 845, in move copy_function(src, real_dst) File "C:\Program Files\Python311\Lib\shutil.py", line 436, in copy2 copyfile(src, dst, follow_symlinks=follow_symlinks) File "C:\Program Files\Python311\Lib\shutil.py", line 256, in copyfile with open(src, 'rb') as fsrc: FileNotFoundError: [Errno 2] No such file or directory: 'C:\\Users\\Andrei\\pyject\\rand_quiz\\capitalsquiz1'
问题根源
- 前缀信息丢失:第一个循环只把序号存入
order列表,后续拼接前缀时用的是最后一次循环的mo.group(1),如果文件夹内文件前缀不一致,会生成错误的旧文件名。 - 修改原始文件名列表:重命名循环中修改了
order[i]的值,导致后续循环的旧路径指向已经被修改的名称,自然找不到文件。 - 正则未匹配扩展名:你的正则没考虑文件后缀(比如
.txt),生成的路径缺少扩展名,系统找不到对应文件。
修复后的代码
import os import re import shutil def fill_gap(folder): print(f'in {folder}') # 匹配带序号的文件名(包含扩展名) num_pattern = re.compile(r'^(.*?)(\d+)(\..*)?$') # 存储完整文件信息:(前缀, 序号, 扩展名, 原始文件名) file_info_list = [] # 遍历文件夹内所有文件 for oldfile in os.listdir(folder): mo = num_pattern.search(oldfile) if not mo: continue prefix = mo.group(1) num = int(mo.group(2)) ext = mo.group(3) or '' # 处理无扩展名的情况 file_info_list.append( (prefix, num, ext, oldfile) ) # 按序号排序 file_info_list.sort(key=lambda x: x[1]) # 生成新文件名并执行重命名 main_path = os.path.abspath(folder) for idx, (prefix, _, ext, old_filename) in enumerate(file_info_list, start=1): old_path = os.path.join(main_path, old_filename) new_filename = f'{prefix}{idx}{ext}' new_path = os.path.join(main_path, new_filename) print(f'renaming "{old_path}" to "{new_path}"...') shutil.move(old_path, new_path) fill_gap(r'C:\Users\Andrei\pyject\rand_quiz')
修复说明
- 正则优化:新增扩展名匹配逻辑,确保文件名完整。
- 存储完整信息:保存每个文件的前缀、序号、扩展名和原始文件名,避免信息丢失。
- 不修改原始列表:循环时直接使用存储的原始文件名,避免路径指向错误。
- 清晰排序逻辑:用lambda表达式直接按序号排序,可读性更强。
内容的提问来源于stack exchange,提问作者Donj
相关产品推荐
相关产品推荐

