Dodawanie folderów do pliku zip za pomocą Pythona
Chcę utworzyć plik zip. Dodaj folder do pliku zip, a następnie dodaj kilka plików do tego folderu.
Więc chcę skończyć z plikiem zip z pojedynczym folderem z plikami w.
Nie wiem, czy to zła praktyka, aby mieć foldery w plikach zip, czy coś, ale google nie daje mi nic na ten temat.
Zacząłem od tego:
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);
Pochodzi z: http://mail.python.org/pipermail/python-list/2006-August/396166.html
Który się pozbawia wszystkie foldery i umieszcza wszystkie pliki w folderze docelowym (i jego podfoldery) w jednym pliku zip. Nie mogłem dodać całego folderu.
Jeśli dodam ścieżkę do folderu w myZipFile.pisz, dostaję
Każda pomoc jest mile widziana.IOError: [Errno 13] Permission denied:'..\ packed\bin '
Podobne pytanie: Jak spakować zawartość folderu używając Pythona (Wersja 2.5)?
12 answers
Ok, po tym jak zrozumiałem, czego chcesz, jest to tak proste, jak użycie drugiego argumentu zipfile.write
, gdzie możesz użyć, co chcesz:
import zipfile
myZipFile = zipfile.ZipFile("zip.zip", "w" )
myZipFile.write("test.py", "dir\\test.py", zipfile.ZIP_DEFLATED )
Tworzy plik zipfile, w którym test.py
zostanie rozpakowany do katalogu o nazwie dir
Edytuj: Kiedyś musiałem utworzyć pusty katalog w pliku zip: jest to możliwe. po powyższym kodzie wystarczy usunąć plik test.py z pliku zipfile plik zniknie, ale pusty katalog pozostanie.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-01-24 11:31:00
Możesz również użyć 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)
Spowoduje to umieszczenie całego folderu w zip.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-02-17 17:34:02
Plik zip nie ma struktury katalogów, ma tylko kilka ścieżek i ich zawartość. Te ścieżki powinny być względem wyimaginowanego folderu głównego (samego pliku ZIP). "../ "prefiksy nie mają zdefiniowanego znaczenia w pliku zip.
Uznaj, że masz plik, a
i chcesz go przechowywać w" folderze " wewnątrz pliku zip. Wszystko, co musisz zrobić, to przedrostek nazwy pliku z nazwą folderu podczas przechowywania pliku w pliku zipfile:
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
Nie znam żadnych implementacji ZIP pozwala na umieszczenie pustego folderu w pliku ZIP. Mogę wymyślić obejście (przechowywanie dummy nazwa pliku w "folderze" zip, który powinien być ignorowany podczas ekstrakcji), ale nie Przenośne w różnych implementacjach.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-01-19 21:34:13
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()
Biegnę:
python tozip.py
To jest dziennik:
havok@fireshield:~$ 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)
Jak widać, działa, archiwum też jest ok. Jest to funkcja rekurencyjna, która może zapinać cały folder. Jedynym problemem jest to, że nie tworzy pustego folderu.
Zdrówko.Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-07-23 14:58:24
Poniżej znajduje się kod do zamocowania całego katalogu do pliku zipfile.
To wydaje się działać OK tworzenie plików zip w systemie windows i linux. Wyjście pliki wydają się prawidłowo rozpakowywać w systemie windows (wbudowana funkcja skompresowanych folderów, WinZip i 7-Zip) oraz linux. Pojawiają się jednak puste katalogi w pliku zip być bolesnym problemem. Poniższe rozwiązanie wydaje się działać, ale wyjście z "zipinfo" na Linuksie jest niepokojące. Również uprawnienia katalogu nie są ustawione poprawnie dla pustych katalogi w archiwum zip. Wydaje się, że wymaga to trochę bardziej dogłębnych badań.
Dostałem kilka informacji z tego wątku velocity reviewsi tego wątku listy dyskusyjnej Pythona.
Zauważ, że ta funkcja jest przeznaczona do umieszczania plików w archiwum zip z albo nie ma katalogu nadrzędnego, albo tylko jeden Katalog nadrzędny, więc przycina wszelkie katalogi wiodące w ścieżkach systemu plików i nie zawierają ich wewnątrz ścieżki archiwum zip. Dzieje się tak zazwyczaj, gdy chcesz po prostu wziąć katalog i zrobić z niego plik zip, który można wyodrębnić w różnych miejsca.
Argumenty ze słowem kluczowym:
DirPath -- ścieżka łańcuchowa do katalogu do archiwum. To jedyny wymagany argument. Może być absolutny lub względny, ale tylko jeden lub zero wiodące katalogi zostaną włączone do archiwum zip.
ZipFilePath -- ścieżka do wyjściowego pliku zip. Może to być absolutna lub ścieżka względna. Jeśli plik zip już istnieje, będzie aktualizacja. Jeśli nie, zostanie stworzony. Jeśli chcesz go zastąpić od zera, usuń go przed wywołaniem tej funkcji. (domyślnie jest obliczana jako dirPath + ".zip")
IncludeDirInZip -- boolean wskazujący, czy katalog najwyższego poziomu powinien być zawarte w archiwum lub pominięte. (default True)
(zauważ, że StackOverflow zdaje się nie drukować mojego Pythona z trzy cytowane ciągi, więc właśnie przekonwertowałem moje ciągi doc na tekst posta tutaj)
#!/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()
Oto niektóre przykładowe zastosowania. Zauważ, że jeśli twój argument dirPath ma kilka wiodących katalogów, domyślnie zostanie uwzględniony tylko ostatni. Pass includeDirInZip=False aby pominąć wszystkie wiodące katalogi.
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")
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-06-29 03:14:07
Oto moja funkcja, której używam do zamykania folderu:
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()
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-10-09 17:04:44
Po dodaniu kilku importów Twój kod działa dobrze dla mnie, jak nazwać skrypt, może mógłbyś nam powiedzieć o strukturze folderów '..\packed \ bin' directory.
Nazwałem Twój kod następującymi argumentami:
planName='test.zip'
files=['z.py',]
folders=['c:\\temp']
(success,filename)=createZipFile(planName,files,folders)
`
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-01-19 17:47:34
Jeśli spojrzysz na plik zip utworzony za pomocą Info-ZIP, zobaczysz, że katalogi są rzeczywiście wymienione:
$ 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
Zauważ, że wpis katalogu ma zerową długość i nie jest skompresowany. Wydaje się, że można osiągnąć to samo z Pythonem, pisząc Katalog po nazwie, ale zmuszając go do nie używania kompresji.
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)
Może warto się upewnić, że arcname
kończy się /
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-08-18 04:41:39
Oto edytowany kod, który uruchomiłem. Opiera się na powyższym kodzie, zaczerpniętym z listy dyskusyjnej. Dodałem import i zrobiłem główną rutynę. Wyciąłem również majstrowanie z nazwą pliku wyjściowego, aby Kod był krótszy.
#!/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])
W pracy, na moim Windows box, ten kod działał dobrze, ale nie stworzył żadnych "folderów" w pliku zipfile. Przynajmniej sobie przypominam. Teraz w domu, na moim Linuksie, utworzony plik zip wydaje się być zły:
$ 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.
Nie wiem, czy przypadkowo złamałem kod, myślę, że jego to samo. Problemy z platformą? Tak czy inaczej, nie jest związany z moim oryginalnym pytaniem; pobieranie folderów w pliku zip. Chciałem tylko dodać kod, który uruchomiłem, a nie kod, na którym bazowałem.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-01-19 22:26:04
Dziękuję bardzo wery za tę przydatną funkcję! Okazało się to bardzo przydatne, ponieważ również szukałem pomocy. Jednak może przydałoby się to trochę zmienić, aby
basedir = os.path.dirname(dirpath) + '/'
Byłoby
basedir = os.path.dirname(dirpath + '/')
Ponieważ okazało się, że jeśli chcę zip folder 'przykład', który znajduje się w 'C:\folder\path\notWanted\to\zip\Example",
Mam w 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'
Ale przypuszczam, że Twój kod powinien dać
dirpath = 'C:\folder\path\notWanted\to\zip\Example'
basedir = 'C:\folder\path\notWanted\to\zip\Example\'
dirname = '\Subfolder_etc'
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-12-15 10:17:30
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()
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-09-17 19:32:24
Gdy chcesz utworzyć pusty folder, możesz to zrobić w następujący sposób:
storage = api.Storage.open("empty_folder.zip","w")
res = storage.open_resource("hannu//","w")
storage.close()
Folder nie wyświetla się w winextractor, ale po rozpakowaniu jest wyświetlany.