-->

Check if a directory exists in a zip file with Pyt

2020-07-06 07:38发布

问题:

Initially I was thinking of using os.path.isdir but I don't think this works for zip files. Is there a way to peek into the zip file and verify that this directory exists? I would like to prevent using unzip -l "$@" as much as possible, but if that's the only solution then I guess I have no choice.

回答1:

Just check the filename with "/" at the end of it.

import zipfile

def isdir(z, name):
    return any(x.startswith("%s/" % name.rstrip("/")) for x in z.namelist())

f = zipfile.ZipFile("sample.zip", "r")
print isdir(f, "a")
print isdir(f, "a/b")
print isdir(f, "a/X")

You use this line

any(x.startswith("%s/" % name.rstrip("/")) for x in z.namelist())

because it is possible that archive contains no directory explicitly; just a path with a directory name.

Execution result:

$ mkdir -p a/b/c/d
$ touch a/X
$ zip -r sample.zip a
adding: a/ (stored 0%)
adding: a/X (stored 0%)
adding: a/b/ (stored 0%)
adding: a/b/c/ (stored 0%)
adding: a/b/c/d/ (stored 0%)

$ python z.py
True
True
False


回答2:

You can check for the directories with ZipFile.namelist().

import os, zipfile
dir = "some/directory/"

z = zipfile.ZipFile("myfile.zip")
if dir in z.namelist():
    print "Found %s!" % dir


回答3:

You can accomplish this using the built-in library ZipFile.

import zipfile
z = zipfile.ZipFile("file.zip")

if "DirName/" in [member.filename for member in z.infolist()]:
    print("Directory exists in archive")

Tested and functional with Python32.



回答4:

for python(>=3.6):

this is how the is_dir() implemented in python source code:

def is_dir(self):
    """Return True if this archive member is a directory."""
    return self.filename[-1] == '/'

It simply checks if the filename ends with a slash /, Can't tell if this will work correctly in some certain circumstances(so IMO it is badly implemented).

for python(<3.6):

as print(zipinfo) will show filemode but no corrsponding property or field is provided, I dive into zipfile module source code and found how it is implemented. (see def __repr__(self): https://github.com/python/cpython/blob/3.6/Lib/zipfile.py)

possibly a bad idea but it will work:

if you want something simple and easy, this will work in most cases but it may fail because in some cases this field will not be printed.

def is_dir(zipinfo):
    return "filemode='d" in zipinfo.__repr__()

Finally:

my solution is to check file mode manually and decide if the referenced file is actually a directory inspired by https://github.com/python/cpython/blob/3.6/Lib/zipfile.py line 391.

def is_dir(fileinfo):
    hi = fileinfo.external_attr >> 16
    return (hi & 0x4000) > 0


标签: python unzip