news 2026/10/20 8:21:15

不解压查看压缩包文件列表:命令行与Python实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
不解压查看压缩包文件列表:命令行与Python实战

做批量文件处理的时间长了,你会发现一个非常朴素却又高频的需求:很多时候你并不想立刻解压,只想先看一眼压缩包里装了什么。获取压缩包文件名列表,这个动作听起来简单,却是归档整理、安全审查、自动化脚本的公共前置步骤。我在日常工作中几乎每天都要和 zip、tar、7z、rar 这类格式打交道,也踩过不少坑,后来把需要的命令和脚本逐步沉淀成了一套固定用法。这篇文章就把这些经验按场景拆开,从命令行到 Python 脚本,再到各种疑难杂症,尽量一次说透。适合正在搭建文件处理流水线的开发者,也适合只想快速查看某个压缩包内容的普通用户。

1. 先想清楚:为什么非要“只看文件名”?

1.1 日常工作里的高频场景

最典型的一个场景,是给一批下载好的压缩包做归档。比如你从网上扒下来一堆资料包,命名都是类似资源编号加日期这种风格,不打开根本不知道里面是图片、文档还是视频。逐个解压看一遍太伤磁盘,而且解压完还要清理临时文件,不如先把每个包的文件名列表导出来,用 grep 搜索关键词,再决定哪些值得保留。这个操作能直接帮你跳过大量无效解压,让归档效率上一个台阶。

第二个常见场景是安全审查。内部或外部传来的压缩包,尤其是客户提供的所谓报表或附件,在落地执行之前,我会先把文件名列表拉出来看一遍。不是每个恶意包都会在文件名上露馅,但至少能看到有没有隐藏的可执行文件、脚本、免安装 exe、批处理文件等。这个习惯帮我挡过很多麻烦,也避免了把可疑文件直接解压到服务器目录里的风险。

第三个场景是自动化流水线。比如给一批压缩包批量归类,逻辑往往是先拿到内部文件列表,再根据扩展名或目录结构自动分配到对应文件夹;或者在数据库里登记压缩包台账,文件名列表就是最直接的元数据。这种情况下不可能手工去解压,必须用命令或脚本批量取。如果你正在写这类自动化脚本,文件名列表这一步就是整个流程的入口,入口稳了,后面一切都顺。

1.2 只取文件名能换来哪些实际好处

首先是不动内容,降低风险。解压操作会把文件实实在在写到磁盘上,如果压缩包里的文件名带有路径穿越特征,解压工具一旦不够安全,就可能写入到预期之外的目录。只列文件名就没有这个风险,最多只是读取中央目录或归档头,不会在磁盘上产生任何实际文件。

其次是省时间和 IO。一个几百兆的压缩包,解压可能要几十秒,但列出文件名通常在一秒内。尤其当包里有大量小文件时,解压的随机 IO 开销非常明显,而读取目录区是顺序读取,两者完全不是一个量级。对于服务器上的临时磁盘或云盘,少解压一次就是实打实的效率提升。

最后是方便配合 grep、awk、sort 等文本工具做二次处理。文件名列表本质上是纯文本,可以连续管道过滤,比如找出所有种子文件的文件名,统计某个目录下的文件大小,这些在命令行里都是一行命令的事。有了纯文本输出,你就能把压缩包当成一个普通的数据源去处理,而不是每次都先动手解开它。

1.3 从需求倒推工具选型

用什么工具去取列表,取决于你手里的压缩包格式、所在系统以及后续要做什么。如果只是临时看一眼,命令行工具是最快的;如果要批量处理并和业务逻辑结合,最好使用编程库。还有一个常被忽略的因素:是否需要保留原文件的编码信息。比如老式 Windows 压缩包的中文文件名,在命令行里可能乱码,但在 Python 里可以通过底层字节做修正。先清楚需求,再去选工具,别一上来就用最复杂的那套。

场景推荐方案理由
临时查看 zipunzip -l / zipinfo -1系统自带,快
临时查看 tartar -tf支持多种 tar 压缩格式
多种格式混合7z l通用,能看较多格式
批量自动化Python zipfile / tarfile接口统一,易扩展
RAR 专属unrar l / rarfileRAR 没有标准库支持

2. 命令行速查:不用解压也能把文件名看得明明白白

2.1 ZIP 系:unzip -l 与 zipinfo 的使用差异

Linux 和 macOS 上一般默认装了 unzip 和 zipinfo。unzip -l 的 l 是 list 的缩写,它会列出一个详细清单,包括长度、日期、时间、文件名。如果你只是想要干净的纯文件名列表,zipinfo -1 更好用,-1 参数的意思是只输出文件名,每行一个,没有任何额外信息。这个输出可以直接进 grep 或 awk,不需要再单独做文本裁剪。

unzip -l demo.zip zipinfo -1 demo.zip # 等价写法 unzip -Z -1 demo.zip

注意,unzip -l 在个别平台上可能要求参数顺序不同,但最常见的形式就是unzip -l 文件名。更需要注意:unzip 在列出某些 zip 时,如果文件名含中文,终端显示可能乱码,这并不影响内部数据,只是显示编码问题。你可以临时设置系统字符集环境变量,或者干脆改用 7z 看。就我自己的体验,不同工具显示同一批文件名的结果可能不一样,因为有些工具会主动猜测编码,有些则严格按压缩包里的标记位处理。

2.2 TAR 系:tar -tf 与压缩格式的配合

tar 是 Linux 下最常用的归档格式,而且它本身不做压缩,.tar.gz、.tar.bz2、.tar.xz 是在 tar 外面又套了一层压缩。不管外面套了什么,tar 工具都能直接识别,前提是系统的 tar 版本够新。命令很简单:tar -tf 包名。有人习惯写tar -tzf,-z 明确指定 gzip,在早期版本确实需要,但现在的 GNU tar 会自动根据文件名后缀判断压缩方式,所以-tf就够了。如果遇到 .tgz,同样可以直接 tar -tf。

tar -tf archive.tar.gz tar -tf archive.tgz tar -tf archive.tar.xz

输出里常见的./前缀,来自打包时使用了相对路径,多数情况下不影响使用,但如果你把文本拿去和预期列表比对,可以先用 sed 去掉。这里有个容易忽略的点:tar 对目录是以/结尾的,文件没有。所以要用列表判断某个路径是不是目录,直接看末尾有没有/就行,比 zip 的目录标记更规整。

2.3 7z / RAR 系:7z l 与 unrar l 的细节

7-Zip 的命令行工具 7z 是跨平台的多格式救星。它的 l 子命令可以列出 7z、zip、rar、tar、gzip、bzip2、xz 等格式的文件名。对于 7z 包,7z l 的输出信息很全,包括时间、属性、大小、压缩后大小、Name。不过默认的人类可读列表并不方便脚本直接提取,我更推荐用-slt参数输出技术信息,然后从Path =行提取文件名。

7z l demo.7z 7z l -slt demo.7z | grep '^Path = ' | sed 's/^Path = //'

RAR 格式要看系统有没有 unrar。unrar l demo.rar就能列出文件名。如果你想得到不带任何属性信息的纯文件路径,unrar lb demo.rar会输出更精简的结果,但不同版本的 unrar 表现略有差异,我习惯先unrar l看一遍整体信息,再决定要不要继续处理。如果没有 unrar,也可以用7z l demo.rar,7z 也能读出 RAR 的目录结构,只是输出风格不太一样。

2.4 通杀方案:一个命令脚本搞定主流格式

把上面的工具串成一个函数,日常用起来很顺手。这个函数不追求复杂,只解决“拿到一个包,立刻看内容”的通用需求。

list_archive() { case "$1" in *.zip) zipinfo -1 "$1" ;; *.tar|*.tar.gz|*.tgz|*.tar.bz2|*.tar.xz) tar -tf "$1" ;; *.7z|*.rar) 7z l -slt "$1" | grep '^Path = ' | sed 's/^Path = //' ;; *) echo "unknown archive: $1" >&2; return 1 ;; esac }

使用方式:list_archive package.7z。但要注意,7z 对某些复合格式例如 .tar.gz 会先展开外层压缩,再列 tar 内部文件,输出可能比 tar -tf 多一层。脚本里我把 .tar.gz 交给了 tar 命令,正是为了避免这种歧义。zipinfo 也可以换成 unzip -Z -1,效果一致。

提示:在不可信的压缩包上执行解压前,先跑一遍unzip -l或7z l,看列表中是否出现../、以/开头的绝对路径等异常路径。如果出现,直接放弃解压,这才是文件列表最实用的安全价值。

3. 编程方式:用脚本批量获取、筛选、入库

3.1 Python 标准库:zipfile 与 tarfile

当需要批量处理几十上百个压缩包时,命令行就不够优雅了。用 Python 可以一次遍历目录、读取列表、做条件判断、写日志,一个脚本全搞定。标准库里的 zipfile 和 tarfile 就是主力。zipfile 读取的是压缩包尾部的中枢目录,所以过程非常快,不需要真的去解压每个文件。注意,zipfile 默认返回的列表包含目录项,也就是以/结尾的名称;如果你只需要文件,建议过滤掉。

import zipfile with zipfile.ZipFile('demo.zip', 'r') as archive: names = archive.namelist() for name in names: print(name)
import tarfile with tarfile.open('demo.tar.gz', 'r:*') as archive: names = archive.getnames() for name in names: print(name)

tarfile 的r:*表示根据文件头自动探测压缩方式,通用性很好。getnames() 返回的是全部成员名,包括目录和文件。如果包特别大,getnames() 会把所有名字一次性放进内存,后面我会给出逐成员迭代的办法。

3.2 第三方库:py7zr 与 rarfile 的接入方式

7z 和 rar 没有标准库支持,需要用第三方库。py7zr 是纯 Python 实现,能够读写 7z 文件,对大部分 7z 版的兼容性也不错;rarfile 则更像一个封装器,它自身并不能处理 RAR 格式,需要在系统上安装 unrar 或 bsdtar,通过外部命令解析。py7zr 的 getnames() 返回的列表可能是 str 列表,也可能带路径分隔符/,用法和 zipfile 差不多。安装方式是pip install py7zr。

import py7zr with py7zr.SevenZipFile('demo.7z', 'r') as archive: names = archive.getnames() print(names)
import rarfile with rarfile.RarFile('demo.rar') as archive: names = archive.namelist() print(names)

使用 rarfile 前,确保环境变量 RARFILE_EXECUTABLE 指向 unrar 可执行文件,或者让 rarfile 在 PATH 里找到 unrar。否则运行时会直接报找不到 unrar。我第一次用的时候就在容器环境里因为这个报错卡了半天,后来把 unrar 装进镜像就彻底解决了。

3.3 实战:按扩展名统计压缩包内文件类别

光拿列表没什么意思,结合筛选才是常见的自动化需求。举个例子:批量检查某个目录下的 zip 包里有没有可执行文件,顺便统计各类型文件的数量。

import glob import zipfile from pathlib import Path from collections import Counter type_counter = Counter() dangerous = [] for zip_path in glob.glob('/data/uploads/*.zip'): with zipfile.ZipFile(zip_path) as archive: for name in archive.namelist(): if name.endswith('/'): continue suffix = Path(name).suffix.lower() type_counter[suffix] += 1 if suffix in {'.exe', '.bat', '.cmd', '.sh', '.ps1', '.js'}: dangerous.append((zip_path, name)) print(type_counter) for zip_path, name in dangerous: print(f'[WARN] {zip_path}: {name}')

这段代码的核心就两个点:一是用name.endswith('/')过滤目录,二是用Path(name).suffix拿扩展名。有人会写 os.path.splitext,也行,但 Path 在跨平台上更省心。如果压缩包是 RAR 或 7z,把 zipfile 对应替换成 rarfile.RarFile 或 py7zr.SevenZipFile 即可,外层遍历逻辑全部保持一致。这种统一接口正是用脚本处理多格式的最大优势。

3.4 编码与路径:绕不开的两个坑

中文文件名乱码,是我在 zip 压缩包上遇到最多的编码问题。旧时代很多 Windows 压缩工具生成的 zip,文件名字段用的是 GBK 或 GB2312,但没有按照 UTF-8 标记设置标志位。Python 的 zipfile 在没有 UTF-8 标志时,默认按 cp437 解码,于是中文变成了一串看不懂的字符。解决办法是把乱码字符串按 cp437 重新编码成原始字节,再用 GBK 解码。反过来,如果确认原始编码是 UTF-8,乱码就不会出现。

import zipfile with zipfile.ZipFile('legacy.zip') as archive: for info in archive.infolist(): name = info.filename raw = name.encode('cp437') for encoding in ('utf-8', 'gbk', 'big5', 'shift_jis'): try: fixed = raw.decode(encoding) break except UnicodeDecodeError: continue else: fixed = raw.decode('utf-8', errors='replace') print(fixed)

注意:这种探测逻辑不能盲用。有些现代 zip 已经是正常 UTF-8,你去做 cp437 编码反而可能触发异常,所以最好先判断名字里是否含有非 ASCII 字符。更好的办法是用 Python 3.11 之后的ZipFile(..., metadata_encoding='utf-8')参数从源头指定解码器,但在旧版本上还是得靠手工转换。

路径分隔符的问题同样隐蔽。zip、7z 内部统一使用/作为分隔符,tar 也可能带./前缀。做字符串匹配时,不要默认地以为所有路径都符合系统分隔符。比如 Linux 上/正常,Windows 上Path(name)也能把它识别成路径,但如果用name.split('/')而不是 os.sep,就能保证跨平台一致性。脚本里我统一用/处理,输出到 Windows 文件系统时再让 pathlib 转换。

4. 常见问题与排查技巧实录

4.1 中文文件名乱码:GBK 与 UTF-8 的纠葛

上面说过一半,这里把排查方法补充完整。当你在 unzip -l 或 zipinfo 输出里看到中文变成乱码,问题几乎都出在编码标记缺失。先在终端多试几个工具对比:7z l 对编码的识别强一点,往往能正确显示,因为它会主动猜;unzip 则严格遵守标记,没标记就按系统默认。用 Python 脚本里的修正是最可控的,你可以把任意一个乱码名字打印成 repr,看到类似特定 Unicode 字符,就说明原始字节来自 GBK。

再把每个乱码字符串重新 encode('cp437'),得到的就是原始字节,接下来按 gbk、big5、shift_jis 等常见编码去尝试。这个流程我封装成了函数,所有项目复用。如果你处理的压缩包是别人从老系统里打包出来的,准备一套编码探测工具几乎是必须的,否则归档系统里永远都有一批读不出名字的文件。

4.2 加密压缩包能看到文件名吗?

很多人以为加密包就什么也看不见,其实要看具体格式和加密方式。传统的 ZIP 加密(ZipCrypto)和 ZIP 标准的 AES 加密,加密的是每个文件的数据部分,中央目录里的文件名通常是明文,所以 unzip -l 依然能看到文件名,只是解压时要密码。RAR 的明文列表也是常见情况。7z 则不一样,7z 格式可以选择加密文件名,也叫头部加密。用 7z l 去列一个头部加密的 7z 包,直接会报错或提示需要密码,文件名列表根本拿不到。

格式文件数据是否加密文件名列表是否可见
ZIP (ZipCrypto/AES)加密通常可见
RAR可加密通常可见
7z(未头部加密)加密可选可见
7z(头部加密)加密不可见,需密码

所以如果你期望对 7z 包也列出文件名,需要先知道密码,或者包没有开启头部加密。遇到这种情况,别再去纠结工具参数,先确认包的加密策略。这也是为什么我会在后端流程里对传入压缩包先做格式识别,再分别处理。

4.3 超大压缩包与内存爆炸:用流式读取避免

当压缩包里有数十万个文件时,namelist() 返回一个几十万项的列表,看起来没什么,但实际上每项都保存了完整的路径字符串和扩展信息,内存占用会翻好几倍。如果这个包还在一个批处理循环里,多个包叠加起来,进程内存很容易冲到很高。命令行工具通常是流式的,unzip -l 和 tar -tf 边读边输出,内存几乎不增长。Python 端也可以尽量流式处理,zipfile 的 namelist() 和 infolist() 没有迭代器,但 tarfile 可以直接迭代成员对象,解决得干净彻底。

import tarfile with tarfile.open('huge.tar.gz', 'r:*') as archive: for member in archive: print(member.name)

zipfile 虽然不能迭代成员,但如果你需要处理超大 zip 并避免一次载入全部信息,可以结合命令行工具,比如 zipinfo -1 管道给 Python 逐行读取。多数正常业务的 zip 包规模不会太大,真遇到超大包,优先采取流式思路而不是硬撑内存。

4.4 嵌套压缩包:先看一层,再决定要不要继续钻进去

压缩包里又套压缩包,是归档管理里常见的情况。最外层的文件名列表里只能看到内层压缩包本身,要想知道内层内容,必须继续解析。这里要注意:不要无脑递归解压,嵌套包有可能被利用来制造超深层级、消耗服务器资源,所以递归要设置最大深度和总文件大小上限。Python 处理嵌套包时,先判断扩展名,如果外层列表里出现的是 .zip、.7z 这类后缀,就把对应文件读入内存字节流,再交给对应的库去解析。

但 RAR 的 rarfile 不直接支持流式对象,通常需要先解压到临时文件;zipfile 和 py7zr 可以处理字节流。为了安全,我建议所有递归操作都在隔离的临时目录内进行,并且只保留最终分析结果,不保留临时文件。嵌套包的递归逻辑写起来并不复杂,真正的难点在于边界控制:什么时候停止,最多解几层,临时文件怎么清理。这些如果考虑不足,很容易在线上跑出事故。

4.5 文件名列表不等于文件内容:安全与完整性提醒

最后一条一定要说:文件名列表只是元数据,不是内容指纹。一个压缩包内叫 note.txt 的文件,内容可能是经过混淆的脚本;一个叫 photo.jpg 的文件,也可能是带恶意载荷的伪装格式。所以拿文件名清单做安全判断,只能作为第一步筛查,不能替代真正的文件扫描或内容审计。

另外,需要重点检查路径穿越特征。如果列表里出现../或者以/开头的绝对路径,这是高风险信号,多数解压器出于安全策略会拒绝写入,但别赌,最好直接标记为异常。对于内容完整性需求,则还需要对每个文件计算哈希或校验值,单纯看列表帮不上忙。把这些注意事项纳入流程后,取文件名列表才真正成为一个稳、准、省时省力的基础操作,而不是看起来简单的表面功夫。

5. 实操中沉淀下来的几条经验

5.1 我的工具使用习惯

实际操作中,我个人的习惯是:单个、未知格式的包,首选 7z l 扫一眼;明确是 zip,就用 zipinfo -1 拿纯列表;明确是 tar,就用 tar -tf。这三个命令已经覆盖了我九成以上的临时需求。批量处理时,只要条件允许,我倾向于用 Python 统一封装,因为后续加筛选、加日志、加告警都方便。有一次我处理一批老客户发来的 zip 资料包,文件名全是 GBK 编码的中文,unzip 在终端里直接乱码。后来我用 Python 把每个包的文件列表按 GBK 修正后导入数据库,再给前端的搜索接口用,整个过程不到半小时。如果没有那层编码修正,这批资料包就只能逐个解压后重命名,费时又费力。

5.2 一个能复用的脚本模板

最后分享一个极简模板,把命令行和 Python 的优点结合起来:先用命令行输出纯文件名列表,再交给 Python 做归类。好处是不需要安装额外库,也能处理超大包。

zipinfo -1 'archive.zip' | python -c " import sys from pathlib import Path from collections import Counter c = Counter() for line in sys.stdin: line = line.rstrip('\n') if not line.endswith('/'): suffix = Path(line).suffix.lower() or '(none)' c[suffix] += 1 print(c) "

这条命令会统计 zip 包内各扩展名的文件数量。如果你处理的是 tar,把 zipinfo -1 换成 tar -tf;处理 7z 或 RAR,换成 7z l -slt 加 grep。组合起来就是一套成本极低的归档扫描流程。这个内容后续还可以继续扩展:把结果写成 JSON、对接通知接口、定时扫描上传目录……不过起点都是同一个动作——先拿到那串文件名列表。基本功打扎实,后面怎么玩都顺手。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/20 8:20:38

RK3576外挂RTL8367RB交换芯片:SPI管理+RGMII数据面实现多口千兆

这块主控板上只有一个原生千兆口,产品却要求至少四个千兆LAN口加一个上联口,光靠板载网口根本不够用。我最后交出来的方案是“RK3576 RTL8367RB(SPI管理模式)”,核心思路很简单:数据面走RGMII,…

作者头像 李华
网站建设 2026/10/20 8:20:29

LLM做推荐系统:技术范式、证据边界与渐进式落地路径

1. 为什么大模型做推荐值得认真对待推荐系统这个行当,过去十年基本是特征工程和深度模型的天下。从最早的协同过滤,到后来的Wide&Deep、DeepFM,再到双塔召回加精排的经典架构,大家拼的是特征质量、样本设计和模型结构的微创新…

作者头像 李华
网站建设 2026/10/20 8:19:59

RDK X5 部署 YOLO:模型转换、BPU 推理与性能优化实战

简介:面向在RDK X5上初探YOLOv5部署的开发者,这份轻量源码包精准对应了从开发环境搭建、数据集训练到模型量化过程中的关键配置需求,尤其适合刚接触地瓜平台的新手对照官方文档快速起步。资源包含3个文件,涵盖inscode环境描述、HT…

作者头像 李华
网站建设 2026/10/20 8:19:44

国产AI会议助手深度拆解:语音识别、信创适配与私有化部署全解析

这两年因为工作关系,我接触了不少会议纪要工具。说实话,一开始我对“国产AI会议助手”这个说法是有点疑虑的,毕竟底层用的模型、算力、框架,很多都是国外的开源方案。但真正深入去部署、去调优、去做信创环境适配之后,…

作者头像 李华
网站建设 2026/10/20 8:19:04

业务软件加AI:直接调模型API还是引入智能体SDK?选型指南

1. 先搞清楚你到底在加什么很多团队一说“给业务软件加 AI”,脑子里浮现的画面就是接个大模型接口,输入问题、返回答案,完事。真动手了才发现,事情远没有这么简单。你面对的第一个岔路口,就是直接调模型 API&#xff0…

作者头像 李华
网站建设 2026/10/20 8:18:07

唤醒老相册的斑驳记忆:用 RAG 检索胶片底片摄影参数与冲洗暗房笔记

书房朝西的木柜第三层,整齐收纳着八大本厚重的中画幅与 135 胶片负片底片册。每当我抽出无酸底片袋,透过透光观片台的柔和白光细细审视那些黑白与彩色底片,总会被一种强烈的时空凝固感所打动。在那个按下快门必须深思熟虑的胶片年代&#xff…

作者头像 李华