如何使用Python创建文件路径的zip文件,包括空目录?
我一直试图使用zipfile
和shutil.make_archive
模块递归创建一个目录的zip文件。两个模块都很好用 - 除了空目录不会被添加到存档中。包含其他空目录的空目录也会被无提示地跳过。如何使用Python创建文件路径的zip文件,包括空目录?
我可以使用7Zip创建相同路径的存档并保留空目录。因此我知道这在文件格式本身内是可能的。我只是不知道如何在Python中做到这一点。有任何想法吗?谢谢!
有使用压缩文件一个例子:
import os, zipfile
from os.path import join
def zipfolder(foldername, filename, includeEmptyDIr=True):
empty_dirs = []
zip = zipfile.ZipFile(filename, 'w', zipfile.ZIP_DEFLATED)
for root, dirs, files in os.walk(foldername):
empty_dirs.extend([dir for dir in dirs if os.listdir(join(root, dir)) == []])
for name in files:
zip.write(join(root ,name))
if includeEmptyDIr:
for dir in empty_dirs:
zif = zipfile.ZipInfo(join(root, dir) + "/")
zip.writestr(zif, "")
empty_dirs = []
zip.close()
if __name__ == "__main__":
zipfolder('test1/noname/', 'zip.zip')
您的代码将绝对路径保存在存档中。我稍微修改它以保存相对路径(因为它将在另一台机器上解压缩),并且它工作得很好!谢谢您的帮助! – jamieb 2012-08-01 04:12:00
是的,我也这样做了,但那很简单。 必须将项目回迁到2.6,所以我必须替换shutil.make_archive()调用。 – 2012-10-03 11:57:20
在Python 2.7.3下进行测试,它不压缩空的dirs,但它确实压缩了其他所有内容。此外,'empty_dirs.extend([如果os.listdir(join(root,dir))== []])在目录中是dir,则只需要为每个根启动,而不是每个启动dir in root(因为空的dirs将会进入) – James 2012-12-19 11:08:49
您需要register a new archive format才能这样做,因为默认的ZIP归档程序不支持该功能。看看the meat of the existing ZIP archiver。使用您当前未使用的变量dirpath
创建目录的归档程序。我找了如何创建一个空的目录,发现this:
zip.writestr(zipfile.ZipInfo('empty/'), '')
有了这一点,你应该能够编写必要的代码,使其归档空目录。
这是从Adding folders to a zip file using python解除,但唯一的功能,我已经试过的作品。列出的答案在Python 2.7.3下不起作用(不复制空目录,效率低下)。被尝试和测试了以下:
#!/usr/bin/python
import os
import zipfile
def zipdir(dirPath=None, zipFilePath=None, includeDirInZip=True):
if not zipFilePath:
zipFilePath = dirPath + ".zip"
if not os.path.isdir(dirPath):
raise OSError("dirPath argument must point to a directory. "
"'%s' does not." % dirPath)
parentDir, dirToZip = os.path.split(dirPath)
#Little nested function to prepare the proper archive path
def trimPath(path):
archivePath = path.replace(parentDir, "", 1)
if parentDir:
archivePath = archivePath.replace(os.path.sep, "", 1)
if not includeDirInZip:
archivePath = archivePath.replace(dirToZip + os.path.sep, "", 1)
return os.path.normcase(archivePath)
outFile = zipfile.ZipFile(zipFilePath, "w",
compression=zipfile.ZIP_DEFLATED)
for (archiveDirPath, dirNames, fileNames) in os.walk(dirPath):
for fileName in fileNames:
filePath = os.path.join(archiveDirPath, fileName)
outFile.write(filePath, trimPath(filePath))
#Make sure we get empty directories as well
if not fileNames and not dirNames:
zipInfo = zipfile.ZipInfo(trimPath(archiveDirPath) + "/")
#some web sites suggest doing
#zipInfo.external_attr = 16
#or
#zipInfo.external_attr = 48
#Here to allow for inserting an empty directory. Still TBD/TODO.
outFile.writestr(zipInfo, "")
outFile.close()
该负责的代码是[这里](http://hg.python.org/cpython/file/8f1a8e80f330/Lib/shutil.py#l452)。 – icktoofay 2012-08-01 02:36:33
尝试在目录中添加一个虚拟文件,然后从存档中删除该文件,以查看zipfile实际上是否支持空目录(某些zip实现虽然不支持该格式)。 – Thomas 2012-08-01 02:38:21