从zip文件中提取文件并在Windows 7上保留mod date-Python 2.7.1

MTA*_*min 19 python zip extraction

我正在尝试使用Python 2.7.1(在Windows上,fyi)从zip文件中提取文件,我的每次尝试都显示提取的文件,其中包含Modified Date =提取时间(这是不正确的).

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()
Run Code Online (Sandbox Code Playgroud)

我也尝试使用.extractall方法,结果相同.

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

谁能告诉我我做错了什么?

我想认为这是可能的,而不必每postcorrect的修改时间在这里

Eth*_*man 14

嗯,它确实需要一些后期处理,但它并没有那么糟糕:

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))
Run Code Online (Sandbox Code Playgroud)

好吧,也许那么糟糕.

  • @RvdK:添加 `(0, 0, -1)` 因为 [`time.mktime`](https://docs.python.org/2/library/time.html#time.mktime) 需要 9 -元素`元组`。“-1”表示“DST”标志未知。 (2认同)

小智 7

基于 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))
Run Code Online (Sandbox Code Playgroud)

要保留日期,只需在提取完成后调用此函数。

这是一个示例,来自我编写的用于压缩/解压缩游戏保存目录的脚本:

        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]
Run Code Online (Sandbox Code Playgroud)

谢谢大家之前的回答!


jia*_*103 6

根据Ber的回答,我开发了这个版本(使用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)
Run Code Online (Sandbox Code Playgroud)

由于目录正在被修改,因为提取的文件是在它们内部创建的os.utime,因此在提取完成之前设置日期似乎毫无意义,因此该版本将目录名称及其时间戳缓存到最后.


Ber*_*Ber 5

根据Ethan Fuman的回答,我开发了此版本(使用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()
Run Code Online (Sandbox Code Playgroud)

这将解压缩到当前工作目录,并使用ZipFile.extract()方法写入数据,而不是创建文件本身。