Python ZipFile 如何判断压缩包内条目为目录还是文件?现有路径判断逻辑失效怎么办?
现有实现的核心缺陷
你之前靠统计路径内句点数量区分文件和目录的逻辑,本质是拿路径命名特征猜类型,天生适配性差:带点的目录名、无扩展名的普通文件都会导致判断完全错误。
对应两个需求的修正方案
B 准确判断条目是目录还是普通文件
完全不需要自己做路径特征推断,ZipFile本身存储了每个条目的类型元数据,直接用封装好的能力判断即可:
- 对每个zip内条目,调用
zipf.getinfo(条目名)获取对应ZipInfo对象 - 直接调用对象的
is_dir()方法判断类型,这个方法是根据zip规范里的条目属性标记做判断,不会被特殊命名的目录、无后缀的文件干扰 - 相比靠“路径是否以斜杠结尾”做判断的野路子,这种方式对损坏zip、第三方工具打包的异常zip兼容性更好
A 准确判断目录是否属于指定目标范围
你之前用if folder in item做包含匹配的逻辑容易出现误判:比如目标目录是MyMod,会把MyModBackup、OtherMod/MyMod这类前缀相似、根本不属于目标范围的路径全部匹配进来。正确的匹配逻辑:
- 先把目标目录做规范化处理:去掉路径末尾冗余的斜杠,补成统一的前缀格式,比如目标路径
GameData/MyMod统一成GameData/MyMod/ - 匹配时要求条目路径严格以规范化后的目标路径为前缀,也就是判断
item.startswith(normalized_target_path),从根上避免前缀相似的误匹配
调整后的核心代码片段
with ZipFile(zipdata, 'r') as zipf: mod_items = zipf.namelist() for folder in mod_folders: # 规范化目标目录路径,插入列表头保证目录优先创建 normalized_folder = folder.rstrip('/') + '/' mod_items.insert(0, normalized_folder) for item in mod_items: # 严格校验条目是否在目标目录范围内 if not item.startswith(normalized_folder): continue # 生成统一的落盘路径 itempath = item if not itempath.startswith('GameData/'): itempath = 'GameData/' + itempath path = path_clear(mod_destination_folder + '/' + itempath) # 用zip元数据直接判断条目类型,不再靠句点数量猜 info = zipf.getinfo(item) if info.is_dir(): makedirs(path, exist_ok=True) else: # 提前创建文件上级目录,不需要等FileNotFoundError再补建 makedirs(path[:path.rfind('/')], exist_ok=True) with open(path, 'wb') as f: f.write(zipf.read(item))
代码里给
makedirs加上exist_ok=True参数,也能去掉原来靠try catch防重复建目录的冗余逻辑。
内容的提问来源于stack exchange,提问作者artificial nonintelligence
相关产品推荐
相关产品推荐

