在不解压ZIP的情况下查看其内容:使用Python标准库列出文件名和大小

プログラミング・Web開発カテゴリを表すパンダのイラスト 编程・Web开发

关于本文
本文是通过利用生成式AI的自动化生成流程创建的。参考Python官方的zipfile文档,整理了在不解压ZIP的情况下确认文件名、大小以及加密标志的方法。

验证状态:📘 参考官方规范确认后编写・所发布的实机运行代码未经实际验证

想查看通过邮件接收的ZIP文件的内容。但是,直接解压未知文件令人感到不安。在这种情况下,有一种方法可以在不解压的情况下读取目录(中心目录)信息。仅使用Python的标准库 zipfile 即可列出文件名、原始大小和压缩后的大小。

项目条件
对象希望安全预先调查ZIP内容的初学者和业务负责人
环境Python 3、要调查的ZIP的副本
额外安装不需要
文件更改仅读取ZIP。不进行解压或覆盖
限制可以查看文件列表,但不保证其内容的安全性或真实性

首先尝试列出文件

将调查对象的副本放在工作文件夹中,命名为 sample.zip ,并将以下 Python 代码保存为 inspect_zip.py 。请注意不要将机密文件名发送到日志或外部服务。

from pathlib import Path
from zipfile import ZipFile, BadZipFile

archive = Path("sample.zip")

try:
    with ZipFile(archive, "r") as zf:
        for item in zf.infolist():
            kind = "DIR" if item.is_dir() else "FILE"
            encrypted = "yes" if item.flag_bits & 0x1 else "no"
            print(
                f"{kind}\t{item.file_size}\t"
                f"{item.compress_size}\t{encrypted}\t{item.filename}"
            )
except (BadZipFile, OSError) as error:
    print(f"ZIPを読み取れません: {error}")

预计会从前往后依次显示:类型、解压后的字节数、压缩后的字节数、加密标志以及文件名。此输出是从规范中推导出的预期结果,而非执行日志。

infolist() 返回的 ZipInfo 包含各个条目的元数据。file_size 是解压后的大小,compress_size 是压缩后的大小。目录可以通过 is_dir() 来判断。

观察要点

观察结果可能的含义下一步应对措施
意外的文件名发送方的解释与内容可能不符不解压直接向发送方确认
解压后的大小异常庞大解压时可能会消耗磁盘空间确认容量和运维限制
加密标志为 yes可能是加密条目通过正规共享途径确认
无法读取 ZIP损坏、格式不符、访问权限等确认原始数据和文件格式

flag_bits & 0x1 仅检查 ZIP 通用用途标志中的加密位。它不评估加密方式或密码强度。 此外,仅获取列表并不等于进行了病毒扫描。

为什么不解压也能知道

ZIP 中除了文件内容之外,还有记录条目名称和大小的中央目录。ZipFile 读取该信息,infolist() 并返回列表。本次代码不会调用 extract() 或 extractall()。因此,不会将 ZIP 内的文件写入指定文件夹。

但这并不意味着 ZIP 解析本身完全无害。对于不受信任的输入,请使用已更新的 Python,并在可能的情况下于隔离环境中处理。

修改一处进行尝试

如果列表很长,for item in zf.infolist(): 的紧后面添加以下条件:

            if item.is_dir():
                continue

这样就可以得到排除了目录条目的文件列表。修改后的预期行为是根据规范推测的,未经运行验证。

失败时的故障排除

  • FileNotFoundError 如果显示 :请检查 ZIP 名称和运行时的当前工作文件夹。在此示例中,它将被捕获为 OSError 。

  • BadZipFile 的情况:可能存在文件损坏或不是 ZIP 格式等原因。请勿仅凭扩展名判断是否为 ZIP。

  • 文件名出现乱码的情况:原因可能是 ZIP 创建工具的字符编码指定或兼容性问题。请不要修改原始 ZIP,而是与创建方进行确认。

  • 列表为空的情况:ZIP 中可能没有任何条目。请勿凭空猜测其中是否存在内容。

注意:查看列表与安全解压是两码事

ZIP 的条目名称中可能包含相对路径或可疑名称。仅确认名称并不意味着可以安全地进行解压。特别是,使用文件名自行构建保存路径的处理需要做好路径遍历防护。请同时注意解压后总尺寸巨大的 ZIP,或是包含大量条目的 ZIP。

本次的方法是解压前的初步确认。它不能替代接收方的确认、恶意软件防范以及按需在隔离环境中进行的检查。

图解:读取 ZIP“目录”的机制

ZIP 并不只是单纯的压缩数据块。它有一个名为“中心目录”的目录,里面整理了各个条目的名称和大小等信息,Python 的 ZipFile 可以利用它来生成列表。将文件实际写出到外部的“解压”与引用 ZIP 中记录的信息的“显示列表”是不同的操作。

flowchart LR
    A["ZIPアーカイブ"] --> B["圧縮された各ファイル"]
    A --> C["中央ディレクトリ(目次)"]
    C --> D["ZipInfoで名前・容量・フラグを読む"]
    D --> E["一覧を表示"]
    E --> F["想定外のファイルを探す"]
    B -.->|"一覧表示では展開しない"| E

此图为概念图,并不严格表示 ZIP 内部的物理存储位置。即使能够读出目录中的名称,也不能保证该条目可以被正常取出或安全执行。如果是从外部接收的 ZIP,目录中的信息也应作为外部输入进行谨慎处理。

制作内容已知的练习用 ZIP

没有必要将未知的文件作为第一个教材。如果你自己制作一个只包含虚构 CSV 和简短说明文的 ZIP,就可以放心地将列表显示的各列与实际内容进行对比。以下代码是新建练习用文件的示例。当同名文件存在时,它会停止运行而不会覆盖。由于在撰写本文时未运行过,以下为预想步骤而非实测步骤。

from pathlib import Path
from zipfile import ZIP_DEFLATED, ZipFile

output = Path("training-archive.zip")
if output.exists():
    raise FileExistsError("同名ファイルがあるため中断します")

with ZipFile(output, "w", compression=ZIP_DEFLATED) as zf:
    zf.writestr("report/summary.csv", "項目,値\nA,1\n")
    zf.writestr("readme.txt", "これは架空の教材です")

print("練習用ZIPを作成しました:", output)

如果在前半部分的列表代码中指定此 ZIP,预计会显示 report/summary.csv 和 readme.txt。由于 ZIP 内并不一定总是独立存在文件夹条目,因此“显示为 2 个文件,但也能看到文件夹”这种表面上的差异并不一定属于异常。此外,字符数和字节数也不一致。在比较包含日语的文本大小时,如果能意识到它在 UTF-8 下占用了多少字节,将有助于进一步理解。

压缩并不一定意味着体积一定会变小

重复内容较多的文章很容易被大幅压缩,而像 JPEG 图像或视频这样已经压缩过的数据,则往往很难变小。对于非常短的字符串,由于压缩所需的附加信息,压缩后反而可能会显得更大。因此,即使显示“压缩后大小大于原始大小”,也不能仅凭这一点判定为文件损坏或攻击。

那么,如果压缩后的大小相对于原始大小小得离谱,又该如何呢?虽然可能是指包含大量相同重复数据的文件,但也需要防范类似“ZIP 炸弹”这样会在解压时消耗大量内存和处理时间的风险。不过,我们既不能仅凭压缩率高这一单一数值来确认为恶意,也不能因为低就判断为安全。必须将文件数量、原始大小总和、格式以及接收目的结合起来综合评估。

解压前确认的顺序

flowchart TD
    A["ZIPの一覧を取得"] --> B{"一覧が読めたか"}
    B -->|"いいえ"| C["破損・形式・対応版を確認して保留"]
    B -->|"はい"| D{"不審なパス・容量・件数があるか"}
    D -->|"はい"| E["展開せず送付元と用途を確認"]
    D -->|"いいえ"| F["暗号化・期待したファイル名を確認"]
    F --> G{"内容を取り出す必要があるか"}
    G -->|"ない"| H["一覧確認のみで終了"]
    G -->|"ある"| I["別の安全な検査・展開工程へ"]

在这个流程中,并不能因为能够读取文件列表就认定为安全。例如,假设在工作中预期只接收一份 PDF 文件,但其中却包含了数十个可执行格式的文件扩展名,这就成为了决定不解压并向接收方进行确认的判断依据。反之,即使只排列着预期的 PDF 名称,也无法得知其内容的真伪或是否混入了恶意软件。

即使 ZIP 内部的名称中包含表示父目录的符号或绝对路径之类的表述,也不会仅通过列表显示就写入到该位置。但是,将该名称直接与保存路径关联的自主解压处理是危险的。路径遍历防护在解压过程中是必不可少的。有加密标志并不意味着安全。加密与否和内容是否可检测是两码事。

在共享文件列表时也要考虑隐私

即使不解压文件本身,内部的文件名有时也可能包含客户名称、案件编号或个人信息。如果直接将其粘贴到调查日志或聊天中,仅凭目录就可能会导致信息泄露。应当缩小共享范围,例如只标明所需的扩展名或数量。即使文件名出现乱码,也不要立即修改名称并重新保存原始 ZIP,而应确认创建工具及字符编码相关的条件。

如果在工作中应用,需将“初步检查”与“安全解压”分离开来

以每天收到的批处理文件为例进行思考。如果预设 ZIP 中包含固定的 CSV,则可以在收到后立即列出文件名、数量和原始大小,并设计将与预期大不相同的文件交由人工确认的流程。这并非检查“内容是否正确”的验证,而是在早期阶段确认“结构看起来是否符合预期”的检查。

在真正处理内容的阶段,则需要采取其他安全措施,例如病毒防护、发送方的可靠性、实际的数据验证以及保存位置的权限等。为了避免将成功获取文件列表与可用作业务数据混为一谈,如果在操作手册中明确规定判定范围,将更便于在实际业务中使用。“不打开就能查明的事情”与“不打开就无法明白的事情”的区分,正是这项微小技术的重要用途。

总结

不要直接解压 ZIP,ZipFile.infolist() 即可通过它检查内部的名称和容量。通过对比原始大小和压缩大小,如果发现非预期的文件或极端的容量,请在解压前停下来进行确认。这不是为了保证安全性,而是为了增加判断依据的小步骤。

官方资料

验证备忘录(2026年11月5日):基于官方文档构建。代码运行、实际 ZIP 验证以及 WordPress 显示确认暂未实施。

文档信息

文章??
在不解压ZIP的情况下查看其内容:使用Python标准库列出文件名和大小
?布日期
更新日期
来源
https://papanda925.com/?p=18493&lang=zh

?可: ?于本站?有相??利的正文及原??表,除非?有?明,可依据 CC BY 4.0 使用。本文可能包含使用生成式AI?建或??的内容。若代??有?可声明,或?接的GitHub???定了?可,?代?以??可?准。引用内容、第三方?料、?片及商?不在本?可范?内。 使用政策

标题和URL已复制