Derek Li
Derek Li

Reputation: 3111

Python: Unzip a file to current working directory but not maintain directory structure in zip

I have a zip file like this:

myArchive.zip
|
-folder1
   |
   --folder2
        |
        ---myimage.jpg

When I try to extract myimage.jpg:

with zipfile.ZipFile('myArchive.zip', 'r') as zfile:
   zfile.extract('folder1/folder2/myimage.jpg')

I will get /folder1/folder2/myimage.jpg in my currently working directory

But I just want myimage.jpg to be extracted to currently working directory, how can I do it?

Upvotes: 3

Views: 6026

Answers (2)

running.t
running.t

Reputation: 5709

Very simple solution would be more or less sth like this:

with zipfile.ZipFile('myArchive.zip', 'r') as zfile:
    unpacked = open('myimage.jpg', 'w')
    unpacked.write(zfile.read('folder1/folder2/myimage.jpg'))
    unpacked.close()

Upvotes: 4

MikeHunter
MikeHunter

Reputation: 4304

Instead of using extract or extractall, just get the data and write it to any file you like. Here's a code sample that does what you want:

import os, sys, time
import zipfile

ENC = 'cp437'
outdir = unicode(os.path.abspath('.'))
outzip = 'c:/1temp/timbersales.zip'
zf = zipfile.ZipFile(outzip, 'r')


for info in zf.infolist():
    fn, dtz = info.filename, info.date_time # , info.file_size

    # some zips have dirs listed as files. Catch
    # and bypass those.
    name = os.path.basename(fn)
    if not name:
        continue

    # get our filename converted from bytes to unicode
    fn_uni = fn.decode(ENC, 'replace')
    bn_uni = os.path.basename(fn_uni)


    # this method is about 15% faster than extractall, and 
    # preserves modify and access dates
    c = zf.open(fn)
    outfile = os.path.join(outdir, bn_uni)

    # try/except to avoid problems with locked files, etc
    # do in chunks to avoid memory problems
    chunk = 2**16
    try:
        with open(outfile, 'wb') as f:
            s = c.read(chunk)
            f.write(s)
            while not len(s) < chunk: 
                s = c.read(chunk)
                f.write(s)
        c.close()
        # set modify and access dates to that inside the zip
        dtout = time.mktime(dtz + (0, 0, -1))
        os.utime(outfile, (dtout, dtout))
    except IOError:
        c.close()

This example does all the files in the zip, but you can easily add a couple of lines to check for specific files. It also will overwrite any files in the work dir with the same name as the one being extracted.

Upvotes: 3

Related Questions