Добавление папок в zip файл с помощью python
Я хочу создать почтовый файл. Добавьте папку в zip файл, а затем добавьте в нее несколько файлов.
Поэтому я хочу получить zip файл с одной папкой с файлами.
Я не знаю, плохо ли иметь папки в zip файлах или что-то в этом роде, но Google не дает мне ничего по этому поводу.
Я начал с этого:
def addFolderToZip(myZipFile,folder):
folder = folder.encode('ascii') #convert path to ascii for ZipFile Method
for file in glob.glob(folder+"/*"):
if os.path.isfile(file):
print file
myZipFile.write(file, os.path.basename(file), zipfile.ZIP_DEFLATED)
elif os.path.isdir(file):
addFolderToZip(myZipFile,file)
def createZipFile(filename,files,folders):
curTime=strftime("__%Y_%m_%d", time.localtime())
filename=filename+curTime;
print filename
zipFilename=utils.getFileName("files", filename+".zip")
myZipFile = zipfile.ZipFile( zipFilename, "w" ) # Open the zip file for writing
for file in files:
file = file.encode('ascii') #convert path to ascii for ZipFile Method
if os.path.isfile(file):
(filepath, filename) = os.path.split(file)
myZipFile.write( file, filename, zipfile.ZIP_DEFLATED )
for folder in folders:
addFolderToZip(myZipFile,folder)
myZipFile.close()
return (1,zipFilename)
(success,filename)=createZipFile(planName,files,folders);
Взято из: http://mail.python.org/pipermail/python-list/2006-August/396166.html
Который избавляется от всех папок и помещает все файлы в целевой папке (и ее подпапках) в один zip файл. Мне не удалось добавить целую папку.
Если я укажу путь к папке в myZipFile.write, я получу
IOError: [Errno 13] Permission denied: '..\packed\bin'
Любая помощь приветствуется.
Смежный вопрос: Как мне сжать содержимое папки, используя python (версия 2.5)?
Ответы
Ответ 1
Хорошо, после того, как я понял, что вы хотите, это так же просто, как использовать второй аргумент zipfile.write
, где вы можете использовать все, что хотите:
import zipfile
myZipFile = zipfile.ZipFile("zip.zip", "w" )
myZipFile.write("test.py", "dir\\test.py", zipfile.ZIP_DEFLATED )
создает zip файл, в котором test.py
будет извлечен в каталог с именем dir
EDIT:
Мне когда-то приходилось создавать пустой каталог в zip файле: это возможно.
после вышеописанного кода просто удалите файл test.py из zip файла, файл исчез, но пустой каталог останется.
Ответ 2
Вы также можете использовать shutil
import shutil
zip_name = 'path\to\zip_file'
directory_name = 'path\to\directory'
# Create 'path\to\zip_file.zip'
shutil.make_archive(zip_name, 'zip', directory_name)
Это поместит всю папку в zip.
Ответ 3
Zip файл не имеет структуры каталогов, он просто содержит пустые имена путей и их содержимое. Эти пути должны относиться к воображаемой корневой папке (самому ZIP файлу). Префиксы "../" не имеют определенного значения в zip файле.
У вас есть файл a
, и вы хотите сохранить его в "папке" внутри zip файла. Все, что вам нужно сделать, это префикс имени файла с именем папки при хранении файла в zip файле:
zipi= zipfile.ZipInfo()
zipi.filename= "folder/a" # this is what you want
zipi.date_time= time.localtime(os.path.getmtime("a"))[:6]
zipi.compress_type= zipfile.ZIP_DEFLATED
filedata= open("a", "rb").read()
zipfile1.writestr(zipi, filedata) # zipfile1 is a zipfile.ZipFile instance
Я не знаю никаких реализаций ZIP, позволяющих включить пустую папку в ZIP файл. Я могу подумать об обходном пути (хранящем фиктивное имя файла в zip-папке), которое следует игнорировать при извлечении), но не переносимо по всем реализациям.
Ответ 4
import zipfile
import os
class ZipUtilities:
def toZip(self, file, filename):
zip_file = zipfile.ZipFile(filename, 'w')
if os.path.isfile(file):
zip_file.write(file)
else:
self.addFolderToZip(zip_file, file)
zip_file.close()
def addFolderToZip(self, zip_file, folder):
for file in os.listdir(folder):
full_path = os.path.join(folder, file)
if os.path.isfile(full_path):
print 'File added: ' + str(full_path)
zip_file.write(full_path)
elif os.path.isdir(full_path):
print 'Entering folder: ' + str(full_path)
self.addFolderToZip(zip_file, full_path)
def main():
utilities = ZipUtilities()
filename = 'TEMP.zip'
directory = 'TEMP'
utilities.toZip(directory, filename)
main()
Я запускаю:
python tozip.py
Это журнал:
[email protected]:~$ python tozip.py
File added: TEMP/NARF (7ª copia)
Entering folder: TEMP/TEMP2
File added: TEMP/TEMP2/NERF (otra copia)
File added: TEMP/TEMP2/NERF (copia)
File added: TEMP/TEMP2/NARF
File added: TEMP/TEMP2/NARF (copia)
File added: TEMP/TEMP2/NARF (otra copia)
Entering folder: TEMP/TEMP2/TEMP3
File added: TEMP/TEMP2/TEMP3/DOCUMENTO DEL FINAL
File added: TEMP/TEMP2/TEMP3/DOCUMENTO DEL FINAL (copia)
File added: TEMP/TEMP2/NERF
File added: TEMP/NARF (copia) (otra copia)
File added: TEMP/NARF (copia) (copia)
File added: TEMP/NARF (6ª copia)
File added: TEMP/NERF (copia) (otra copia)
File added: TEMP/NERF (4ª copia)
File added: TEMP/NERF (otra copia)
File added: TEMP/NERF (3ª copia)
File added: TEMP/NERF (6ª copia)
File added: TEMP/NERF (copia)
File added: TEMP/NERF (5ª copia)
File added: TEMP/NARF (8ª copia)
File added: TEMP/NARF (3ª copia)
File added: TEMP/NARF (5ª copia)
File added: TEMP/NERF (copia) (3ª copia)
File added: TEMP/NARF
File added: TEMP/NERF (copia) (copia)
File added: TEMP/NERF (8ª copia)
File added: TEMP/NERF (7ª copia)
File added: TEMP/NARF (copia)
File added: TEMP/NARF (otra copia)
File added: TEMP/NARF (4ª copia)
File added: TEMP/NERF
File added: TEMP/NARF (copia) (3ª copia)
Как вы можете видеть, это работает, архив тоже в порядке. Это рекурсивная функция, которая может застегивать всю папку. Единственная проблема заключается в том, что она не создает пустую папку.
Приветствия.
Ответ 5
Ниже приведен код для застегивания целой директории в zip файл.
Кажется, что это работает ОК, создавая zip файлы как в окнах, так и в linux. Выход
файлы, кажется, правильно извлекаются на окнах (встроенная функция "Сжатые папки",
WinZip и 7-Zip) и Linux. Однако появляются пустые каталоги в zip файле
быть тернистым вопросом. Решение, похоже, работает, но выход
"zipinfo" в linux касается. Также не разрешены права доступа к каталогу
правильно для пустых каталогов в zip-архиве. Это, по-видимому, требует
более глубокие исследования.
У меня есть информация из эта скорость просматривает поток и this поток рассылки python.
Обратите внимание, что эта функция предназначена для размещения файлов в zip-архиве с помощью
ни родительский каталог, ни один родительский каталог, поэтому он
ведущие каталоги в пути файловой системы и не включать их внутри
zip-архивные пути. Это обычно происходит, когда вы хотите просто взять
каталог и превратить его в zip файл, который можно извлечь в разных
местах.
Аргументы ключевого слова:
dirPath - строка в каталог для архивирования. Это единственное
требуемый аргумент. Он может быть абсолютным или относительным, но только один или ноль
ведущие каталоги будут включены в zip-архив.
zipFilePath - строковый путь к выходному zip файлу. Это может быть абсолютным
или относительный путь. Если zip файл уже существует, он будет обновлен. Если
нет, он будет создан. Если вы хотите заменить его с нуля, удалите его
до вызова этой функции. (по умолчанию вычисляется как dirPath + ".zip" )
includeDirInZip - boolean, указывающий, должен ли каталог верхнего уровня
быть включенным в архив или опущен. (по умолчанию 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 имеет несколько ведущих каталогов, по умолчанию будет включен только LAST. Pass 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")
Ответ 6
вот моя функция, которую я использую, чтобы застегнуть папку:
import os
import os.path
import zipfile
def zip_dir(dirpath, zippath):
fzip = zipfile.ZipFile(zippath, 'w', zipfile.ZIP_DEFLATED)
basedir = os.path.dirname(dirpath) + '/'
for root, dirs, files in os.walk(dirpath):
if os.path.basename(root)[0] == '.':
continue #skip hidden directories
dirname = root.replace(basedir, '')
for f in files:
if f[-1] == '~' or (f[0] == '.' and f != '.htaccess'):
#skip backup files and all hidden files except .htaccess
continue
fzip.write(root + '/' + f, dirname + '/' + f)
fzip.close()
Ответ 7
после добавления некоторых импортных кодов для меня отлично работает, как вы называете script, может быть, вы могли бы рассказать нам о структуре папок каталога "..\pack\bin".
Я назвал ваш код следующими аргументами:
planName='test.zip'
files=['z.py',]
folders=['c:\\temp']
(success,filename)=createZipFile(planName,files,folders)
`
Ответ 8
Если вы посмотрите на zip файл, созданный с помощью Info-ZIP, вы увидите, что каталоги действительно перечислены:
$ zip foo.zip -r foo
adding: foo/ (stored 0%)
adding: foo/foo.jpg (deflated 84%)
$ less foo.zip
Archive: foo.zip
Length Method Size Cmpr Date Time CRC-32 Name
-------- ------ ------- ---- ---------- ----- -------- ----
0 Stored 0 0% 2013-08-18 14:32 00000000 foo/
476320 Defl:N 77941 84% 2013-08-18 14:31 55a52268 foo/foo.jpg
-------- ------- --- -------
476320 77941 84% 2 files
Обратите внимание, что запись в каталоге имеет нулевую длину и не сжата. Кажется, вы можете добиться того же самого с Python, написав каталог по имени, но вынуждая его не использовать сжатие.
if os.path.isdir(name):
zf.write(name, arcname=arcname, compress_type=zipfile.ZIP_STORED)
else:
zf.write(name, arcname=arcname, compress_type=zipfile.ZIP_DEFLATED)
Возможно, стоит убедиться, что arcname
заканчивается на /
.
Ответ 9
Вот редактируемый код, который я запускал. Он основан на приведенном выше коде, взятом из списка рассылки. Я добавил импорт и сделал основную процедуру. Я также вырезал возиться с выходным именем файла, чтобы сделать код короче.
#!/usr/bin/env python
import os, zipfile, glob, sys
def addFolderToZip(myZipFile,folder):
folder = folder.encode('ascii') #convert path to ascii for ZipFile Method
for file in glob.glob(folder+"/*"):
if os.path.isfile(file):
print file
myZipFile.write(file, os.path.basename(file), zipfile.ZIP_DEFLATED)
elif os.path.isdir(file):
addFolderToZip(myZipFile,file)
def createZipFile(filename,files,folders):
myZipFile = zipfile.ZipFile( filename, "w" ) # Open the zip file for writing
for file in files:
file = file.encode('ascii') #convert path to ascii for ZipFile Method
if os.path.isfile(file):
(filepath, filename) = os.path.split(file)
myZipFile.write( file, filename, zipfile.ZIP_DEFLATED )
for folder in folders:
addFolderToZip(myZipFile,folder)
myZipFile.close()
return (1,filename)
if __name__=="__main__":
#put everything in sys.argv[1] in out.zip, skip files
print createZipFile("out.zip", [], sys.argv[1])
На работе, в моем окне Windows, этот код работал нормально, но не создавал никаких "папок" в zip файле. По крайней мере, я это помню. Теперь у себя дома, на моем Linux-сервере, созданный zip файл кажется плохим:
$ unzip -l out.zip
Archive: out.zip
End-of-central-directory signature not found. Either this file is not
a zipfile, or it constitutes one disk of a multi-part archive. In the
latter case the central directory and zipfile comment will be found on
the last disk(s) of this archive.
unzip: cannot find zipfile directory in one of out.zip or
out.zip.zip, and cannot find out.zip.ZIP, period.
Я не знаю, случайно ли я сломал код, я думаю, что он такой же. Проблемы с кроссплатформой? В любом случае, это не связано с моим первоначальным вопросом; получение папок в zip файле. Просто хотел опубликовать код, который я на самом деле выполнял, а не код, на котором был основан мой код.
Ответ 10
Большое спасибо за эту полезную функцию! Я нашел его очень полезным, так как искал помощи. Однако, возможно, было бы полезно немного изменить его, чтобы
basedir = os.path.dirname(dirpath) + '/'
будет
basedir = os.path.dirname(dirpath + '/')
Потому что обнаружил, что если я хочу закрепить папку "Пример", которая находится в папке "C:\folder\path\notWanted\to\zip\Example",
Я попал в Windows:
dirpath = 'C:\folder\path\notWanted\to\zip\Example'
basedir = 'C:\folder\path\notWanted\to\zip\Example/'
dirname = 'C:\folder\path\notWanted\to\zip\Example\Example\Subfolder_etc'
Но я полагаю, что ваш код должен давать
dirpath = 'C:\folder\path\notWanted\to\zip\Example'
basedir = 'C:\folder\path\notWanted\to\zip\Example\'
dirname = '\Subfolder_etc'
Ответ 11
import os
import zipfile
zf = zipfile.ZipFile("file.zip", "w")
for file in os.listdir(os.curdir):
if not file.endswith('.zip') and os.path.isfile(os.curdir+'/'+file):
print file
zf.write(file)
elif os.path.isdir(os.curdir+'/'+file):
print f
for f in os.listdir(os.curdir+'/'+file):
zf.write(file+'\\'+f)
zf.close()
Ответ 12
Самый простой способ для меня - использовать zipfile CLI (интерфейс командной строки). CLI zipfile может принимать файлы или папки в качестве аргументов и рекурсивно добавлять их в архив.
Так что если у вас есть файловая иерархия:
- file1.txt
- folder1
- file2.txt
- file3.txt
И вы хотите, чтобы все это было заархивировано в "result.zip", вы просто пишете:
python -m zipfile -c result.zip file1.txt folder
Если вы хотите использовать его в коде Python и использовать импортированный модуль zipfile, вы можете вызвать его основную функцию следующим образом:
import zipfile
zipfile.main(['-c', 'result.zip', 'file1.md', 'folder'])
Ответ 13
Когда вы хотите создать пустую папку, вы можете сделать это следующим образом:
storage = api.Storage.open("empty_folder.zip","w")
res = storage.open_resource("hannu//","w")
storage.close()
Папка не отображается в файле winextractor, но когда вы ее извлекаете, она отображается.