我一直試圖使用zipfile
和shutil.make_archive
模塊遞歸創建一個目錄的zip文件。兩個模塊都很好用 - 除了空目錄不會被添加到存檔中。包含其他空目錄的空目錄也會被無提示地跳過。如何使用Python創建文件路徑的zip文件,包括空目錄?
我可以使用7Zip創建相同路徑的存檔並保留空目錄。因此我知道這在文件格式本身內是可能的。我只是不知道如何在Python中做到這一點。有任何想法嗎?謝謝!
我一直試圖使用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