@ wrote... (3 years, 1 month ago)

I was working on Magic Wormhole during a Pycon 2016 sprint and noticed that zipfiles don't preserve file permissions. I'm not the only one who's noticed this (some posts go back over five years) but it still doesn't appear to be fixed.

Anyhow, here's how I did it…

During creation of the zipfile

import zipfile

with zipfile.ZipFile("outzip.zip", "w", zipfile.ZIP_DEFLATED) as zf:
    zf.write( "somefile" )

the file permissions are stored so the problem lies in the extraction. The easy way just defaults all files to 644 (or whatever your umask is).

with zipfile.ZipFile("outzip.zip", "r") as zf:
    zf.extractall()

so we need to get a little fancy

def extract_file( zf, info, extract_dir ):
    zf.extract( info.filename, path=extract_dir )
    out_path = os.path.join( extract_dir, info.filename )

    perm = info.external_attr >> 16L
    os.chmod( out_path, perm )

with zipfile.ZipFile(zipname, 'r') as zf:
    for info in zf.infolist():
        extract_file( zf, info, extract_dir )

So there you have it.

Category: tech, Tags: python
Comments: 1
Comments
1.
Graham Lyons @ July 12, 2017 wrote... (2 years ago)

This was super-useful - I couldn't see why Zip archives extracted via Python lost their file permissions.

It turns out that the extract method actually returns the path it extracts to so you can lose the os.path.join and out_path can be assigned like:

out_path = zf.extract( info.filename, path=extract_dir )
Click here to add a comment