Извлеките файлы из zip-файла и сохраните дату обновления - Python 2.7.1 в Windows 7 - PullRequest
17 голосов
/ 22 марта 2012

Я пытаюсь извлечь файлы из zip-файла, используя Python 2.7.1 (в Windows, fyi), и каждая из моих попыток показывает извлеченные файлы с измененной датой = время извлечения (что неверно).

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()

Я также пытался использовать метод .extractall, с теми же результатами.

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

Может кто-нибудь сказать мне, что я делаю не так?

Я хотел бы думать, что это возможно без необходимости посткорректировать Модифицированное время за здесь

Ответы [ 4 ]

13 голосов
/ 22 марта 2012

Ну, это займет немного пост-обработки, но это не так уж плохо:

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))

Хорошо, может быть, это так плохо.

5 голосов
/ 04 апреля 2016

Основываясь на ответе Бер, я разработал эту версию (с использованием Python 2.7.11), которая также учитывает даты модификации каталогов.

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)

Поскольку каталоги изменяются по мере создания извлеченных файловвнутри них, по-видимому, нет смысла устанавливать их даты с os.utime до тех пор, пока не будет завершено извлечение, поэтому эта версия кэширует имена каталогов и их временные метки до самого конца.

4 голосов
/ 17 апреля 2014

Основываясь на ответе Итана Фумана, я разработал эту версию (с использованием Python 2.6.6), которая немного более удобна:

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()

Это извлечение в текущий рабочий каталог и использование ZipFile.extract() метод для записи данных вместо создания самого файла.

1 голос
/ 06 января 2018

Основываясь на ответе Jia103, я разработал функцию (используя Python 2.7.14), которая сохраняет даты каталогов и файлов ПОСЛЕ того, как все было извлечено. Это изолирует любое уродство в функции, и вы также можете использовать zipfile.Zipfile.extractAll () или любой другой метод извлечения zip:

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))

Чтобы сохранить даты, просто вызовите эту функцию после завершения извлечения.

Вот пример, из сценария, который я написал для zip / unzip каталогов сохранения игр:

        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]

Спасибо всем за ваши предыдущие ответы!

...