2012-03-21 17 views
8

Estoy tratando de extraer archivos de un archivo zip usando Python 2.7.1 (en Windows, fyi) y cada uno de mis intentos muestra archivos extraídos con fecha modificada = hora de extracción (que es incorrecta).Extraiga archivos del archivo zip y conserve la fecha del mod- Python 2.7.1 en Windows 7

import os,zipfile 
outDirectory = 'C:\\_TEMP\\' 
inFile = 'test.zip' 
fh = open(os.path.join(outDirectory,inFile),'rb') 
z = zipfile.ZipFile(fh) 
for name in z.namelist(): 
    z.extract(name,outDirectory) 
fh.close() 

También probé utilizando el método .extractall, con los mismos resultados.

import os,zipfile 
outDirectory = 'C:\\_TEMP\\' 
inFile = 'test.zip' 
zFile = zipfile.ZipFile(os.path.join(outDirectory,inFile))   
zFile.extractall(outDirectory) 

¿Alguien me puede decir lo que estoy haciendo mal?

Me gustaría pensar que esto es posible sin tener que postcorrect la hora de modificación por here

+1

Vas a estar MUY decepcionado ... –

Respuesta

8

Bueno, hace falta un poco de post-procesamiento, pero no es tan malo:

import os 
import zipfile 
import time 

outDirectory = 'C:\\TEMP\\' 
inFile = 'test.zip' 
fh = open(os.path.join(outDirectory,inFile),'rb') 
z = zipfile.ZipFile(fh) 

for f in z.infolist(): 
    name, date_time = f.filename, f.date_time 
    name = os.path.join(outDirectory, name) 
    with open(name, 'wb') as outFile: 
     outFile.write(z.open(f).read()) 
    date_time = time.mktime(date_time + (0, 0, -1)) 
    os.utime(name, (date_time, date_time)) 

De acuerdo, tal vez es tan malo.

+1

Eso funciona, gracias. Solo como aclaración, ¿mantener la fecha de modificación de la extracción de archivos es una limitación de la implementación del archivo zip de Python o es esta funcionalidad estándar en todas las librerías zip? – MTAdmin

+0

Han pasado 5 años desde la respuesta, y aún funciona bajo Python 3.6. Todavía es feo como el día que lo escribiste, pero funciona. – EndermanAPM

+0

@EndermanAPM: ¡Gracias, lo tomaré como un cumplido! ;) –

4

Sobre la base de la respuesta de Ethan Fuman, he desarrollado esta versión (usando Python 2.6.6) que es un poco más conciso:

zf = ZipFile('archive.zip', 'r') 
for zi in zf.infolist(): 
    zf.extract(zi) 
    date_time = time.mktime(zi.date_time + (0, 0, -1)) 
    os.utime(zi.filename, (date_time, date_time)) 
zf.close() 

Esto extrae en el directorio de trabajo actual y utiliza el ZipFile.extract () método para escribir los datos en lugar de crear el archivo en sí.

3

Basado en la respuesta de Ber, he desarrollado esta versión (usando Python 2.7.11), que también da cuenta de las fechas del modificador de directorio.

from os import path, utime 
from sys import exit 
from time import mktime 
from zipfile import ZipFile 

def unzip(zipfile, outDirectory): 
    dirs = {} 

    with ZipFile(zipfile, 'r') as z: 
     for f in z.infolist(): 
      name, date_time = f.filename, f.date_time 
      name = path.join(outDirectory, name) 
      z.extract(f, outDirectory) 

      # still need to adjust the dt o/w item will have the current dt 
      date_time = mktime(f.date_time + (0, 0, -1)) 

      if (path.isdir(name)): 
       # changes to dir dt will have no effect right now since files are 
       # being created inside of it; hold the dt and apply it later 
       dirs[name] = date_time 
      else: 
       utime(name, (date_time, date_time)) 

    # done creating files, now update dir dt 
    for name in dirs: 
     date_time = dirs[name] 
     utime(name, (date_time, date_time)) 

if __name__ == "__main__": 

    unzip('archive.zip', 'out') 

    exit(0) 

Desde directorios están siendo modificados como los archivos extraídos se están creando en su interior, no parece haber ningún punto en el establecimiento de sus fechas con os.utime hasta después de la extracción se ha completado, por lo que esta versión almacena en caché los nombres de directorio y su marcas de tiempo hasta el final.

0

Basado en la respuesta de Jia103, he desarrollado una función (usando Python 2.7.14) que preserva el directorio y las fechas de archivo DESPUÉS de que se haya extraído todo. Esto aísla cualquier fealdad en la función, y también se puede utilizar zipfile.Zipfile.extractAll() o lo que sea zip extracto de método que desea:

import time 
import zipfile 
import os 

# Restores the timestamps of zipfile contents. 
def RestoreTimestampsOfZipContents(zipname, extract_dir): 
    for f in zipfile.ZipFile(zipname, 'r').infolist(): 
     # path to this extracted f-item 
     fullpath = os.path.join(extract_dir, f.filename) 
     # still need to adjust the dt o/w item will have the current dt 
     date_time = time.mktime(f.date_time + (0, 0, -1)) 
     # update dt 
     os.utime(fullpath, (date_time, date_time)) 

Para preservar las fechas, simplemente llamar a esta función después de su extracto se hace.

He aquí un ejemplo, a partir de un guión que escribí para comprimir/descomprimir juego guardar directorios:

 z = zipfile.ZipFile(zipname, 'r') 
     print 'I have opened zipfile %s, ready to extract into %s' \ 
       % (zipname, gamedir) 
     try: os.makedirs(gamedir) 
     except: pass # Most of the time dir already exists 
     z.extractall(gamedir) 
     RestoreTimestampsOfZipContents(zipname, gamedir) #<-- USED 
     print '%s zip extract done' % GameName[game] 

Gracias a todos por sus respuestas anteriores!

Cuestiones relacionadas