Extract files from zip file and retain mod date?

前端 未结 4 1363
迷失自我
迷失自我 2020-12-05 14:48

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

相关标签:
4条回答
  • 2020-12-05 15:11

    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.

    0 讨论(0)
  • 2020-12-05 15:16

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

    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.

    0 讨论(0)
  • 2020-12-05 15:17

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

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

    Thanks everyone for your previous answers!

    0 讨论(0)
  • 2020-12-05 15:18

    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.

    0 讨论(0)
提交回复
热议问题