2016-03-29 17 views
7

Ho un file zip che contiene tre file zip in questo modo:Come estrarre file zip in modo ricorsivo in Python

zipfile.zip\ 
    dirA.zip\ 
     a 
    dirB.zip\ 
     b 
    dirC.zip\ 
     c 

voglio estrarre tutti i file zip interiori che sono all'interno del file zip nella directory con questi nomi (dirA, dirB, dirC).
Fondamentalmente, io voglio finire con il seguente schema:

output\ 
    dirA\ 
     a 
    dirB\ 
     b 
    dirC\ 
     c 

Ho provato quanto segue:

import os, re 
from zipfile import ZipFile 

os.makedirs(directory) # where directory is "\output" 
with ZipFile(self.archive_name, "r") as archive: 
    for id, files in data.items(): 
     if files: 
      print("Creating", id) 
      dirpath = os.path.join(directory, id) 

      os.mkdir(dirpath) 

      for file in files: 
       match = pattern.match(filename) 
       new = match.group(2) 
       new_filename = os.path.join(dirpath, new) 

       content = archive.open(file).read() 
      with open(new_filename, "wb") as outfile: 
       outfile.write(content) 

Ma estrae solo il file zip e io alla fine con:

output\ 
    dirA\ 
     dirA.zip 
    dirB\ 
     dirB.zip 
    dirC\ 
     dirC.zip 

Qualsiasi suggerimento compresi i segmenti di codice sarà molto apprezzato perché ho provato così tante diverse t le ali e leggere i documenti senza successo.

+0

Modifica la domanda e fornire un [_Minimal, completa e verificabile example_] (https://stackoverflow.com/help/mcve) che include ciò che è in 'data.items()'. – martineau

+0

@martineau Grazie per il tuo commento. Come descritto in precedenza, i dati vale \ zipfile.zip> dirA.zip> un \ zipfile.zip> dirB.zip> b \ zipfile.zip> dirC.zip> c ho cercato di rendere la questione un po ' più generale e non dipendente da qualsiasi "dato", tranne per il fatto che ci sono zip all'interno di un zip. – Yannis

risposta

4

Durante l'estrazione del file zip, è necessario scrivere i file zip interni in memoria anziché su disco. Per fare questo, ho usato BytesIO.

Partenza di questo codice:

import os 
import io 
import zipfile 

def extract(filename): 
    z = zipfile.ZipFile(filename) 
    for f in z.namelist(): 
     # get directory name from file 
     dirname = os.path.splitext(f)[0] 
     # create new directory 
     os.mkdir(dirname) 
     # read inner zip file into bytes buffer 
     content = io.BytesIO(z.read(f)) 
     zip_file = zipfile.ZipFile(content) 
     for i in zip_file.namelist(): 
      zip_file.extract(i, dirname) 

Se si esegue extract("zipfile.zip") con zipfile.zip come:

zipfile.zip/ 
    dirA.zip/ 
     a 
    dirB.zip/ 
     b 
    dirC.zip/ 
     c 

uscita dovrebbe essere:

dirA/ 
    a 
dirB/ 
    b 
dirC/ 
    c 
+0

@Yannis verifica la risposta aggiornata. – Forge

+0

Esattamente quello che stavo cercando, fa l'estrazione come descritto nella mia domanda. Grazie! – Yannis

+0

@Forge Errore: sub_zip non definito –

0

Per una funzione che estrae una zip nidificato file (qualsiasi livello di nidificazione) e pulisce i file zip originali:

import zipfile, re, os 

def extract_nested_zip(zippedFile, toFolder): 
    """ Extract a zip file including any nested zip files 
     Delete the zip file(s) after extraction 
    """ 
    with zipfile.ZipFile(zippedFile, 'r') as zfile: 
     zfile.extractall(path=toFolder) 
    os.remove(zippedFile) 
    for root, dirs, files in os.walk(toFolder): 
     for filename in files: 
      if re.search(r'\.zip$', filename): 
       fileSpec = os.path.join(root, filename) 
       extract_nested_zip(fileSpec, root) 
Problemi correlati