最初我想使用
os.path.isdir
但我认为这不适用于 zip 文件。有没有办法查看 zip 文件并验证该目录是否存在?我想尽可能避免使用 unzip -l "$@"
,但如果这是唯一的解决方案,那么我想我别无选择。
只需检查文件名末尾带有“/”的文件即可。
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")
您使用这条线
any(x.startswith("%s/" % name.rstrip("/")) for x in z.namelist())
因为 archive 可能不明确包含目录;只是一个带有目录名称的路径。
执行结果:
$ 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
您可以使用 ZipFile.namelist() 检查目录。
import os, zipfile
dir = "some/directory/"
z = zipfile.ZipFile("myfile.zip")
if dir in z.namelist():
print "Found %s!" % dir
这就是
is_dir()
在 python 源代码中的实现方式:
def is_dir(self):
"""Return True if this archive member is a directory."""
return self.filename[-1] == '/'
它只是检查文件名是否以斜杠结尾
/
,无法判断这在某些特定情况下是否能正常工作(所以在我看来,它实施得很糟糕)。
因为
print(zipinfo)
将显示 filemode
但没有提供相应的属性或字段,我深入研究 zipfile 模块源代码并发现它是如何实现的。
(参见def __repr__(self):
https://github.com/python/cpython/blob/3.6/Lib/zipfile.py)
如果您想要简单易用的东西,这在大多数情况下都可以工作,但可能会失败,因为在某些情况下该字段不会被打印。
def is_dir(zipinfo):
return "filemode='d" in zipinfo.__repr__()
我的解决方案是手动检查文件模式,并确定引用的文件是否实际上是受https://github.com/python/cpython/blob/3.6/Lib/zipfile.py第391行启发的目录。
def is_dir(fileinfo):
hi = fileinfo.external_attr >> 16
return (hi & 0x4000) > 0
您可以使用内置库 ZipFile 来完成此操作。
import zipfile
z = zipfile.ZipFile("file.zip")
if "DirName/" in [member.filename for member in z.infolist()]:
print("Directory exists in archive")
已通过 Python32 测试并正常运行。
此处未列出,但这可以通过字典查找来完成。
import os, zipfile
def zip_contains_dir(zip_handle, path):
# Ensure trailing slash.
path = path.rstrip("/") + "/"
return path in zip_handle.NameToInfo
with zipfile.ZipFile("myfile.zip") as zip_handle:
print(zip_contains_dir(zip_handle, "some/dir"))