工作上遇到一个问题,QA提供的1000多个压缩文件名称命名不规范,服务器做C++覆盖率产物解析,压缩文件文件名必须和解压之后的文件名一致,所以只是修改压缩文件名称行不通,必须逐个解压之后重命名文件夹,再打包成压缩文件,用Python脚本实现了下,有需要自取做下改造。
这边实现的需求是批量把文件名类似“test_P0_500_1085____1.zip”的压缩文件先解压,之后重命名成:test_main_<index>文件名之后再重新压缩成压缩文件。
一、实现过程中遇到的几个坑
1. Python文件重命名和删除
重命名文件夹使用shutil.move()方法,删除文件夹用shutil.rmtree()方法,删除单个文件用os.remove()方法。
2. Python文件压缩类型设置
在使用zipfile.ZipFile()方法的时候,如果没有加compression参数,文件只是添加到压缩文件中,实际上并没有进行压缩操作,会维持源文件的大小。
3. Python文件压缩目录配置
使用z.write()方法压缩文件,没有传第二个参数会把压缩文件所在的根目录完整路径层级一并压缩到压缩文件中;
不能只传fileName,这样压缩出来的文件在解压之后不会有文件夹目录。最好加上压缩文件夹名称,这样在Unbuntu环境下用命令解压之后会解压到压缩前所在的folder文件夹,而不会把压缩包里面的文件都解压到当前路径中。
4. allowZip64配置为开启
在压缩文件超过2GB的时候,如果没有配置allowZip64为True,就会抛异常,在配置为True的情况下,压缩文件超过2GB会使用ZIP64扩展来创建压缩文件。详细见:bugs python issue21866
实现脚本源码如下:
# -*- coding: utf-8 -*-
import os
import zipfile
import shutil
"""
批量重命名压缩文件,sourceFolder为源压缩文件所在文件夹,destFolder为解压重命名再压缩之后的目标文件夹
"""
def batchRenameZip(sourceFolder, destFolder):
source = os.walk(sourceFolder, "r")
index = 1
for path,dir_list,file_list in source:
for fileName in file_list:
if fileName.find(".zip") < 0 or fileName.find("___") < 0:
continue
sourceZipPath = os.path.join(path, fileName)
index+=1
print(sourceZipPath)
try:
zFile = zipfile.ZipFile(sourceZipPath, "r")
for member in zFile.namelist():
zFile.extract(member, destFolder)
zFile.close();
folderName = fileName[0:fileName.find("___")]
renameFolder = "test_main_" + str(index)
#重命名文件夹
shutil.move(destFolder + folderName, destFolder + renameFolder)
#压缩重命名之后的文件夹
compressFile(destFolder + renameFolder + ".zip", destFolder + renameFolder, renameFolder)
#删除解压之后的文件夹,保留压缩文件,删除文件夹用shutil.rmtree()方法
shutil.rmtree(destFolder + renameFolder)
#看自己的需要,是否要删除源压缩文件,删除单个文件用os.remove()方法
#os.remove(sourceZipPath)
except Exception as err:
"""
异常捕获处理,避免源压缩文件本身已损坏的问题
如果源压缩文件有问题会输出"File is not a zip file"
"""
print err
# zipPath是压缩之后的文件路径,compressFolder是要压缩的文件夹路径,folder是压缩之后所在文件夹名称
def compressFile(zipPath, compressFolder, folder):
if os.path.isfile(compressFolder):
with zipfile.ZipFile(zipPath, 'w', compression=zipfile.ZIP_DEFLATED, allowZip64=True) as z:
z.write(compressFolder)
else:
# 这边如果没有传compression参数,则文件只是打包到压缩文件里面,并没有进行压缩
with zipfile.ZipFile(zipPath, 'w', compression=zipfile.ZIP_DEFLATED, allowZip64=True) as z:
for root, dirs, files in os.walk(compressFolder):
for fileName in files:
if fileName != zipPath:
filePath = os.path.join(root, fileName)
z.write(filePath, folder + "/" + fileName)
if __name__ == '__main__':
batchRenameZip("/Users/chenwenguan/Downloads/testRename/", "/Users/chenwenguan/Downloads/testRenameSecond/")
二、其他参考资料
python中zipfile、tarfile压缩文件模块的使用
Python之文件与目录操作(os、zipfile、tarfile、shutil)
扩展阅读:
转载请注明出处:陈文管的博客 – Python批量重命名压缩文件
扫码或搜索:文呓
微信公众号 扫一扫关注