Skip to content Skip to sidebar Skip to footer

Extract Files From Zip File And Retain Mod Date?

I'm trying to extract files from a zip file using Python 2.7.1 (on Windows, fyi) and each of my attempts shows extracted files with Modified Date = time of extraction (which is inc

Solution 1:

Well, it does take a little post-processing, but it's not that bad:

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

Okay, maybe it is that bad.

Solution 2:

Based on Ethan Fuman's answer, I have developed this version (using Python 2.6.6) which is a little more consise:

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

This extracts to the current working directory and uses the ZipFile.extract() method to write the data instead of creating the file itself.

Solution 3:

Based on Jia103's answer, I have developed a function (using Python 2.7.14) which preserves directory and file dates AFTER everything has been extracted. This isolates any ugliness in the function, and you can also use zipfile.Zipfile.extractAll() or whatever zip extract method you want:

import time
import zipfile
import os

# Restores the timestamps of zipfile contents.defRestoreTimestampsOfZipContents(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))

To preserve dates, just call this function after your extract is done.

Here's an example, from a script I wrote to zip/unzip game save directories:

        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)  #<--  USEDprint'%s zip extract done' % GameName[game]

Thanks everyone for your previous answers!

Solution 4:

Based on Ber's answer, I have developed this version (using Python 2.7.11), which also accounts for directory mod dates.

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

defunzip(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 dtfor name in dirs:
       date_time = dirs[name]
       utime(name, (date_time, date_time))

if __name__ == "__main__":

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

    exit(0)

Since directories are being modified as the extracted files are being created inside them, there appears to be no point in setting their dates with os.utime until after the extraction has completed, so this version caches the directory names and their timestamps till the very end.

Post a Comment for "Extract Files From Zip File And Retain Mod Date?"