Python批量重命名Excel文件时遭遇[Errno 2]文件未找到及AttributeError问题排查
问题排查与修复方案
首先,咱们来拆解你遇到的两个核心问题,以及代码里的其他潜在Bug:
1. AttributeError: 'str' object has no attribute 'is_file' 的根源
os.listdir() 返回的是指定路径下文件名的字符串列表,不是 pathlib.Path 对象。所以当你尝试调用 files.is_file() 或者 file.is_file() 时,本质是在对字符串调用只有Path对象才有的方法,自然会报错。
2. 代码里的其他关键问题
extract_date函数逻辑错误:函数内部循环遍历所有文件,然后直接return ws['C5'].value,这意味着它只会返回第一个Excel文件的C5值,而不是每个文件自己的C5内容,完全不符合批量重命名的需求。- 变量名冲突与循环逻辑混乱:比如在
user_choice == 'y'的分支里,for file in os.path.join(SPEC_PATH, file):这行存在两个问题:一是变量名file重复使用,二是os.path.join返回的是字符串,遍历字符串会逐个字符迭代,这完全不是你想要的遍历文件的逻辑。 - 重命名逻辑错误:你尝试用
file.rename(),但如果file是字符串的话,根本没有这个方法;而且新文件名的拼接也有问题,比如new_name = f"{head_string}{file.suffix}"没有用到从C5提取的内容,和需求不符。 - 路径处理不一致:混合使用
os模块和pathlib模块的路径处理方式,容易导致路径格式混乱,建议统一用pathlib来处理所有路径操作,更简洁可靠。
修复后的完整代码
下面是修正了所有问题的代码,完全符合你的需求:
import pathlib import re from openpyxl import load_workbook # 获取用户输入路径并转为绝对路径 spec_path = pathlib.Path(input("请输入文件路径: ")).resolve() def format_name(raw_name): # 清理文件名中不合法的字符 return re.sub(r"[^\w\-_. ]", "", str(raw_name)) def extract_cell_value(file_path, cell="C5"): # 提取指定Excel文件中指定单元格的值 try: wb = load_workbook(file_path, read_only=True) ws = wb.active cell_value = ws[cell].value wb.close() # 确保提取的值不为空,否则返回默认标识 return str(cell_value) if cell_value is not None else f"未识别内容_{file_path.stem}" except Exception as e: print(f"读取文件 {file_path.name} 失败: {e}") return f"读取失败_{file_path.stem}" # 主逻辑 user_choice = input("是否需要在新文件名前添加前缀字符串?(y/n) ").strip().lower() # 统一获取路径下所有Excel文件 excel_files = [f for f in spec_path.iterdir() if f.suffix in (".xls", ".xlsx") and f.is_file()] if not excel_files: print("指定路径下没有找到Excel文件!") else: prefix = "" if user_choice == 'y': prefix = input("请输入前缀字符串: ").strip() # 清理前缀中的非法字符 prefix = format_name(prefix) success_count = 0 for file in excel_files: # 提取当前文件的C5单元格内容 cell_content = extract_cell_value(file) # 格式化单元格内容作为文件名主体 formatted_name = format_name(cell_content) # 拼接新文件名 if prefix: new_file_name = f"{prefix}_{formatted_name}{file.suffix}" else: new_file_name = f"{formatted_name}{file.suffix}" # 构造新的文件路径 new_file_path = spec_path / new_file_name # 避免重名覆盖,若已存在则添加数字后缀 counter = 1 while new_file_path.exists(): new_file_name = f"{formatted_name}_{counter}{file.suffix}" if not prefix else f"{prefix}_{formatted_name}_{counter}{file.suffix}" new_file_path = spec_path / new_file_name counter += 1 try: file.rename(new_file_path) print(f"成功重命名: {file.name} -> {new_file_name}") success_count += 1 except OSError as e: print(f"重命名 {file.name} 失败: {e}") print(f"\n批量重命名完成,成功处理 {success_count}/{len(excel_files)} 个文件")
修复说明
- 统一使用
pathlib:所有路径操作都用pathlib.Path对象,彻底避免字符串路径的各种问题,is_file()、rename()等方法都能正常调用。 - 修正
extract_cell_value函数:改为接收单个文件路径作为参数,返回该文件的指定单元格内容,确保每个文件都能获取自己的C5值。 - 添加文件名合法性处理:用正则清理文件名中的非法字符,避免重命名时因字符不合法报错。
- 重名处理逻辑:如果新文件名已存在,自动添加数字后缀,防止文件被覆盖。
- 错误捕获与提示:增加了文件读取和重命名的错误捕获,方便排查单个文件的问题。
- 清晰的流程逻辑:先获取所有Excel文件,再根据用户选择处理前缀,最后逐个重命名,逻辑更清晰易懂。
内容的提问来源于stack exchange,提问作者NoobQuestions1
相关产品推荐
相关产品推荐

