如何用Python zipfile模块将Zip子目录JPG文件以根目录名+增量编号重命名
问题描述
现有一个Zip文件myzip.zip,目录结构如下:
myzip.zip - directory 1 - subdirectory 1 - imageA.jpg - imageB.jpg - directory 2 - subdirectory 2 - imageA.jpg - imageB.jpg
需求是将其中的.jpg文件重命名为「根目录名-递增序号.jpg」的格式,同时保留原有目录结构,最终输出一个新的Zip文件,修改后结构如下:
myzip_renamed.zip - directory 1 - subdirectory 1 - directory 1-1.jpg - directory 1-2.jpg - directory 2 - subdirectory 2 - directory 2-1.jpg - directory 2-2.jpg
已尝试使用zipfile模块编写初步代码,但不确定实现逻辑是否正确:
import zipfile source = zipfile.ZipFile("myzip.zip", 'r') target = zipfile.ZipFile(source.filename+"_renamed"+".zip", 'w', zipfile.ZIP_DEFLATED) for file in source.infolist(): filename = file.filename #directory 1/subdirectory 1/imageA.jpg rootname, image_name = filename.split("/subdirectory") # rootname results in: directory 1 # image_name results in /subdirectory/image_name.jpg new_image = image_name.replace(image_name, "/subdirectory/"+rootname+image_name[4:]) target.write(rootname+new_image)
解决方案
核心思路
- 遍历源Zip中的所有文件,区分
.jpg文件、目录和其他文件 - 对每个根目录下的
.jpg文件按顺序从1开始递增计数 - 保留原目录结构,仅修改
.jpg文件的文件名 - 将所有文件(含重命名后的图片)写入新的Zip文件,保留原文件元数据
完整实现代码
import zipfile from collections import defaultdict # 打开源Zip文件,创建目标Zip文件 source_zip = zipfile.ZipFile("myzip.zip", "r") target_zip = zipfile.ZipFile("myzip_renamed.zip", "w", zipfile.ZIP_DEFLATED) # 用于记录每个根目录下当前处理的图片序号 current_counter = defaultdict(int) for info in source_zip.infolist(): filename = info.filename # 处理目录:直接写入目标Zip,保留目录结构 if filename.endswith("/"): target_zip.writestr(info, source_zip.read(info)) continue # 处理非jpg文件:直接复制原文件到目标Zip if not filename.lower().endswith(".jpg"): target_zip.writestr(info, source_zip.read(info)) continue # 处理jpg文件:重命名并写入 path_parts = filename.split("/") root_dir = path_parts[0] current_counter[root_dir] += 1 # 拼接新的文件路径:保留根目录和子目录,替换文件名 sub_dir_path = "/".join(path_parts[1:-1]) new_filename = f"{root_dir}-{current_counter[root_dir]}.jpg" new_full_path = f"{root_dir}/{sub_dir_path}/{new_filename}" if sub_dir_path else f"{root_dir}/{new_filename}" # 保留原文件的元数据(如修改时间、权限) new_info = zipfile.ZipInfo(new_full_path, info.date_time) new_info.external_attr = info.external_attr # 写入重命名后的文件内容 target_zip.writestr(new_info, source_zip.read(info)) # 关闭文件句柄 source_zip.close() target_zip.close()
关键细节说明
- 路径兼容:Zip内部统一使用
/作为路径分隔符,通过split("/")拆分路径,避免跨系统路径问题 - 序号计数:使用
defaultdict自动初始化每个根目录的计数器,确保每个根目录下的图片序号从1开始递增 - 元数据保留:复制原
ZipInfo对象的日期时间和外部属性,保证新Zip文件与原文件的元信息一致 - 结构完整:直接复制目录和非图片文件,确保原有目录结构不被破坏
内容的提问来源于stack exchange,提问作者Tobias S
相关产品推荐
相关产品推荐

