Ниже приведен код для архивирования всего каталога в zip-файл.
Кажется, это работает нормально, создавая zip-файлы в Windows и Linux. Выход
файлы, кажется, извлекаются правильно в Windows (встроенная функция сжатых папок,
WinZip и 7-Zip) и Linux. Однако в zip-файле появляются пустые каталоги
быть сложной проблемой. Решение ниже, кажется, работает, но вывод
"zipinfo" на linux касается. Также права доступа к каталогу не установлены
правильно для пустых каталогов в zip-архиве. Это требует
еще несколько углубленных исследований.
Я получил некоторую информацию от этой ветки отзывов о скорости и этой ветки списка рассылки python .
Обратите внимание, что эта функция предназначена для помещения файлов в zip-архив с
либо нет родительского каталога или только один родительский каталог, поэтому он будет обрезать любой
ведущие каталоги в путях файловой системы и не включать их в
пути к zip-архивам. Это обычно тот случай, когда вы хотите просто взять
каталог и превратить его в zip-файл, который можно распаковать в разные
местах.
Аргументы ключевых слов:
dirPath - строковый путь к каталогу для архивирования. Это единственный
обязательный аргумент. Может быть абсолютным или относительным, но только один или ноль
ведущие каталоги будут включены в zip-архив.
zipFilePath - строковый путь к выходному zip-файлу. Это может быть абсолютным
или относительный путь. Если zip-файл уже существует, он будет обновлен. Если
нет, это будет создано. Если вы хотите заменить его с нуля, удалите его
до вызова этой функции. (по умолчанию вычисляется как dirPath + ".zip")
includeDirInZip - логическое значение, указывающее, должен ли каталог верхнего уровня
быть включены в архив или опущены. (по умолчанию True)
(Обратите внимание, что StackOverflow, похоже, не в состоянии распечатать мой питон с
строки в тройных кавычках, поэтому я просто преобразовал свои строки документа в текст сообщения)
#!/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()
Вот несколько примеров использования. Обратите внимание, что если ваш аргумент dirPath имеет несколько ведущих каталогов, по умолчанию будет включен только последний. Передайте includeDirInZip = False, чтобы пропустить все ведущие каталоги.
zipdir("foo") #Just give it a dir and get a .zip file
zipdir("foo", "foo2.zip") #Get a .zip file with a specific file name
zipdir("foo", "foo3nodir.zip", False) #Omit the top level directory
zipdir("../test1/foo", "foo4nopardirs.zip")