xz 命令详解与参数实测(Ubuntu 22.04)
XZ Utils 全参数实测:默认级别 6、-0~-9 与 -9e 预设的非单调形态、-T0 多线程 3.3 倍加速且更小、-l/-lv 流块信息、-t 截断样本制作要点与尾部垃圾严格校验、-M 内存上限字典降级、FD 37 7A 58 5A 00 文件头解析及与 gzip/bzip2 横向对比
xz 命令详解与参数实测(Ubuntu 22.04)
目标:全面掌握 XZ Utils 的 LZMA2 压缩器实战用法——默认级别 6 的原位压缩与元数据保留、
-0-9与-9e预设的实测耗时体积(含-2/-3偏大、-5全场最小、-6-9持平、-9e反而更大的完整形态)、-T0多线程在 118 MiB 大文件上 3.3 倍加速且更小的双收益、-l/-lv流与块信息、-t完整性测试与截断样本的制作要点、-M内存上限的字典降级机制、FD 37 7A 58 5A 00文件头逐字节解析、对尾部垃圾数据的严格校验行为,以及与 gzip、bzip2 的横向对比,全部命令与回显已在 Ubuntu 22.04(xz 5.2.5)实测通过。
一、环境信息
本节列出本文所有实测所依赖的环境与测试数据,便于读者按同规格复现。
- 操作系统:Ubuntu 22.04.5 LTS(x86_64)
- xz 版本:xz (XZ Utils) 5.2.5,liblzma 5.2.5(
xz --version实测两行分别显示) - xz 属于
xz-utils软件包,Ubuntu 22.04 默认预装,无需额外安装 - 同族命令:unxz(解压)、xzcat(解压到标准输出)、xzgrep(压缩文件上 grep)、lzma/lzcat(兼容老格式),随 xz-utils 一并提供
- 实测环境资源:12 逻辑核(
nproc),物理内存 40,067 MiB(xz --info-memory实测) - 演示目录:
/root/demo/xz/ - 测试数据:
log.txt(seq 1 500000生成,3,388,895 字节)、rand.bin(/dev/urandom取 1 MiB,1,048,576 字节,不可压数据代表)、ls.bin(/bin/ls副本,138,216 字节,真实可执行程序代表);多线程实测另用big.txt(seq 1 15000000,123,888,897 字节)
二、命令概览
2.1 语法与测试数据准备
xz 的基本语法是 xz [OPTION]... [FILE]...:默认在 .xz 格式下压缩(原位替换),-d 解压;FILE 为 - 或缺失时读标准输入。与 gzip/bzip2 相同的「压缩即删源」习惯之外,xz 有两个专属特性需要提前知道:其一,压缩预设 -0~-9 是「字典大小、匹配器参数」的组合包,帮助明确警告 7-9 级会显著抬高压缩与解压的内存需求;其二,xz 支持多线程压缩(-T),大文件上提速明显。
💡 技术拓展:
.xz是一种封装格式——外层是流(Stream)结构,内层可含多个块(Block),每个块独立用 LZMA2 编码,尾部带 CRC64/SHA-256 等校验。这一结构正是-l能列出流/块明细、-T能多线程分块压缩的基础。
先准备演示数据:
rm -rf /root/demo/xz && mkdir -p /root/demo/xz && cd /root/demo/xz
seq 1 500000 > log.txt
head -c 1M /dev/urandom > rand.bin
cp /bin/ls ls.bin
验证文件清单与大小:
$ ls -l
total 4472
-rw-r--r-- 1 root root 3388895 Oct 15 18:26 log.txt
-rwxr-xr-x 1 root root 138216 Oct 15 18:26 ls.bin
-rw-r--r-- 1 root root 1048576 Oct 15 18:26 rand.bin
2.2 --help 全量回显
xz --help 输出短帮助(常用参数清单,实测原样保留;高级参数在 xz --long-help):
Usage: xz [OPTION]... [FILE]...
Compress or decompress FILEs in the .xz format.
-z, --compress force compression
-d, --decompress force decompression
-t, --test test compressed file integrity
-l, --list list information about .xz files
-k, --keep keep (don't delete) input files
-f, --force force overwrite of output file and (de)compress links
-c, --stdout write to standard output and don't delete input files
-0 ... -9 compression preset; default is 6; take compressor *and*
decompressor memory usage into account before using 7-9!
-e, --extreme try to improve compression ratio by using more CPU time;
does not affect decompressor memory requirements
-T, --threads=NUM use at most NUM threads; the default is 1; set to 0
to use as many threads as there are processor cores
-q, --quiet suppress warnings; specify twice to suppress errors too
-v, --verbose be verbose; specify twice for even more verbose
-h, --help display this short help and exit
-H, --long-help display the long help (lists also the advanced options)
-V, --version display the version number and exit
With no FILE, or when FILE is -, read standard input.
Report bugs to <lasse.collin@tukaani.org> (in English or Finnish).
XZ Utils home page: <https://tukaani.org/xz/>
帮助里两处加粗级别的提示值得划线:-0 ... -9 默认 6,且使用 7-9 前要把压缩与解压两端的内存占用都算清楚(3.4 节有 -M 的配套实测);-T0 表示用满全部处理器核心(3.5 节实测)。
2.3 版本与内存确认
确认实测环境的 xz 版本与资源状况:
$ xz --version
xz (XZ Utils) 5.2.5
liblzma 5.2.5
$ nproc
12
$ xz --info-memory | head -6
Total amount of physical memory (RAM): 40067 MiB (42012700672 B)
Memory usage limit for compression: Disabled
Memory usage limit for decompression: Disabled
解读:--version 同时给出 xz 工具与 liblzma 库版本——xz 的能力主体在 liblzma 库中,排查问题时两者都要看。--info-memory 显示当前内存限制为 Disabled(未设限),这是 -M 实测(3.10 节)的基准状态。
三、参数逐项实测
3.1 默认压缩(级别 6):原位替换与元数据保留
与 gzip/bzip2 一致,xz 默认压缩并删除原文件,权限与时间戳保留:
$ touch -d "2026-10-15 09:30:00" log.txt && chmod 740 log.txt && ls -l log.txt
-rwxr----- 1 root root 3388895 Oct 15 09:30 log.txt
$ xz log.txt
$ ls -l log.txt.xz
-rwxr----- 1 root root 133816 Oct 15 09:30 log.txt.xz
$ file log.txt.xz
log.txt.xz: XZ compressed data, checksum CRC64
$ xz -d log.txt.xz
$ ls -l log.txt
-rwxr----- 1 root root 3388895 Oct 15 09:30 log.txt
解读:log.txt(3,388,895 字节)压成 log.txt.xz(133,816 字节,约 3.9%)——对比 gzip 的 31.5%、bzip2 的 18.1%,xz 的压缩率优势是数量级的。file 输出点出 .xz 流的校验类型 checksum CRC64(.xz 格式的默认校验)。解压后逐字节还原(3,388,895 字节),权限 -rwxr----- 与 mtime 完整保留。
3.2 -k 保留原文件
-k(keep)让压缩与解压都保留输入文件:
$ xz -k log.txt
$ ls -l log.txt log.txt.xz
-rwxr----- 1 root root 3388895 Oct 15 09:30 log.txt
-rwxr----- 1 root root 133816 Oct 15 09:30 log.txt.xz
$ xz -d -k log.txt.xz; echo rc=$?
xz: log.txt: File exists
rc=1
$ xz -d -k -f log.txt.xz; echo rc=$?
rc=0
$ ls -l log.txt log.txt.xz
-rwxr----- 1 root root 3388895 Oct 15 09:30 log.txt
-rwxr----- 1 root root 133816 Oct 15 09:30 log.txt.xz
$ rm -f log.txt.xz
解读:解压目标已存在时拒绝覆盖,报 File exists、退出码 1(gzip 的对应提示是 already exists; not overwritten、退出码 2,措辞与退出码都不同);加 -f 后强制覆盖。-k 是「压缩留底」场景的必备参数。
3.3 -d 解压与 unxz 等价
xz -d 与独立命令 unxz 完全等价:
$ xz log.txt
$ ls -l log.txt.xz
-rwxr----- 1 root root 133816 Oct 15 09:30 log.txt.xz
$ xz -d log.txt.xz
$ ls -l log.txt
-rwxr----- 1 root root 3388895 Oct 15 09:30 log.txt
$ xz log.txt
$ unxz log.txt.xz
$ ls -l log.txt
-rwxr----- 1 root root 3388895 Oct 15 09:30 log.txt
$ wc -l log.txt && tail -2 log.txt
500000 log.txt
499999
500000
解读:两种方式解压结果一致(500000 行、末两行 499999/500000)。.xz 后缀是识别依据;unxz 即默认解压模式的 xz。
3.4 压缩级别 -0~-9 与 -9e(默认 6)
xz 的预设 -0~-9 是字典与匹配器参数的组合包,默认 -6。先确认默认级别:
$ xz -6 -k log.txt
$ ls -l log.txt.xz && rm -f log.txt.xz
-rwxr----- 1 root root 133816 Oct 15 09:30 log.txt.xz
逐级实测(-k 保留源文件,每级压完即删 .xz):
$ time xz -0 -k log.txt
0.045 s
$ ls -l log.txt.xz && rm -f log.txt.xz
-rwxr----- 1 root root 128036 Oct 15 09:30 log.txt.xz
$ time xz -1 -k log.txt
0.056 s
$ ls -l log.txt.xz && rm -f log.txt.xz
-rwxr----- 1 root root 80100 Oct 15 09:30 log.txt.xz
$ time xz -4 -k log.txt
0.632 s
$ ls -l log.txt.xz && rm -f log.txt.xz
-rwxr----- 1 root root 52052 Oct 15 09:30 log.txt.xz
$ time xz -5 -k log.txt
0.593 s
$ ls -l log.txt.xz && rm -f log.txt.xz
-rwxr----- 1 root root 47856 Oct 15 09:30 log.txt.xz
$ time xz -6 -k log.txt
0.772 s
$ ls -l log.txt.xz && rm -f log.txt.xz
-rwxr----- 1 root root 133816 Oct 15 09:30 log.txt.xz
$ time xz -9e -k log.txt
1.014 s
$ ls -l log.txt.xz && rm -f log.txt.xz
-rwxr----- 1 root root 177964 Oct 15 09:30 log.txt.xz
全级别汇总(3,388,895 字节的 log.txt,实测):
| 级别 | 耗时 | 产物大小(字节) |
|---|---|---|
| -0 | 0.045 s | 128,036 |
| -1 | 0.056 s | 80,100 |
| -2 | 0.122 s | 178,208 |
| -3 | 0.194 s | 178,796 |
| -4 | 0.632 s | 52,052 |
| -5 | 0.593 s | 47,856(全场最小) |
| -6(默认) | 0.772 s | 133,816 |
| -7 | 0.793 s | 133,816 |
| -8 | 0.768 s | 133,816 |
| -9 | 0.778 s | 133,816 |
| -9e | 1.014 s | 177,964 |
解读与结论——这是三篇压缩器实测中形态最「反直觉」的一组:
- 非单调且分段跳变:
-2/-3(约 178 KB)比-0(128 KB)还大;-4/-5突然降到 52 KB/47.9 KB(最优区);-6~-9四级产物完全相同(133,816 字节)——本数据集上默认级别反而比-4/-5大 1.8 倍。 -9e(extreme,用更多 CPU 换压缩率)得到 177,964 字节,比-6大 33%——-e改变的是搜索策略,不保证更小。- 耗时随级别总体上升(0.045 s → 1.014 s,约 22 倍),但产物大小与耗时完全不成正比。
- 帮助里「7-9 级注意内存」的警告针对的是压缩/解压两侧的字典内存(
-9默认字典 64 MiB,解压端同样需要),与小文件上「白花时间还更大」的实测结论相互印证。
💡 要点:对 xz,「拍脑袋选
-9e」在真实数据上可能既慢又大。正确姿势是对代表性数据实测几个级别;本数据集的最优解是-5(47,856 字节),比默认-6小 64%。
3.5 -T 多线程压缩
-T1 单线程与 -T0(用满 12 核)在 123,888,897 字节的 big.txt 上对比:
$ seq 1 15000000 > big.txt && ls -l big.txt
-rw-r--r-- 1 root root 123888897 Oct 15 18:26 big.txt
$ time xz -k -T1 -6 big.txt
18.617 s
$ ls -l big.txt.xz
-rw-r--r-- 1 root root 2149132 Oct 15 18:26 big.txt.xz
$ xz -l big.txt.xz
Strms Blocks Compressed Uncompressed Ratio Check Filename
1 1 2098.8 KiB 118.1 MiB 0.017 CRC64 big.txt.xz
$ rm -f big.txt.xz
$ time xz -k -T0 -6 big.txt
5.621 s
$ ls -l big.txt.xz
-rw-r--r-- 1 root root 1853480 Oct 15 18:26 big.txt.xz
$ xz -l big.txt.xz
Strms Blocks Compressed Uncompressed Ratio Check Filename
1 5 1810.0 KiB 118.1 MiB 0.015 CRC64 big.txt.xz
$ rm -f big.txt.xz
$ rm -f big.txt
解读:
- 速度:
-T0用 5.621 s 对比-T1的 18.617 s,加速约 3.3 倍(12 核未线性扩展,受内存带宽与块分配制约)。 - 体积:多线程产物反而更小(1,853,480 字节对比 2,149,132 字节)。
xz -l揭示了原因——-T1的文件是 1 个 Block,-T0被切成 5 个 Block 并行压缩;分块后各块独立匹配,对这份 seq 数据恰好更紧凑。 .xz的流/块结构让多线程成为可能:块与块之间并行,每块内仍是完整的 LZMA2 编码,解压端无感知。
💡 要点:大文件压缩脚本默认写
xz -T0基本是免费收益(更快且本例更小);但注意多线程会按线程数放大内存占用(每线程一份字典),低内存运行环境要配合-M限流(3.10 节)。小文件无需-T,分块本身也有少量开销。
3.6 -t 完整性测试与截断样本的制作要点
-t 校验压缩文件完整性,不写出文件:
$ xz -k log.txt
$ xz -t log.txt.xz; echo rc=$?
rc=0
$ xz -tv log.txt.xz
log.txt.xz: 130.7 KiB / 3309.5 KiB = 0.039
用 head -c 制造「截断样本」时有个容易踩的坑——截断字节数必须小于压缩文件实际大小:
$ head -c 300000 log.txt.xz > broken.xz
$ ls -l log.txt.xz broken.xz
-rw-r--r-- 1 root root 133816 Oct 15 18:26 broken.xz
-rwxr----- 1 root root 133816 Oct 15 09:30 log.txt.xz
$ xz -t broken.xz; echo rc=$?
rc=0
$ rm -f log.txt.xz broken.xz
解读:源文件只有 133,816 字节,head -c 300000 截不完,broken.xz 实际是完整副本,所以 -t 通过——这次「损坏实验」什么也没损坏。补测用真实小于文件大小的截断点(100,000 字节)验证损坏识别:
$ xz -k log.txt && head -c 100000 log.txt.xz > broken.xz && ls -l log.txt.xz broken.xz && xz -t broken.xz; echo trunc_rc=$?
-rw-r--r-- 1 root root 100000 Oct 15 18:50 broken.xz
-rwxr----- 1 root root 133816 Oct 15 09:30 log.txt.xz
xz: broken.xz: Unexpected end of input
trunc_rc=1
解读:截断文件报 Unexpected end of input、退出码 1——.xz 流有尾部长度与索引校验,缺失即判坏。
xz 对尾部垃圾的态度比 gzip/bzip2 严格得多:
$ xz -k log.txt && cp log.txt.xz appended.xz && printf "XYZ" >> appended.xz && xz -t appended.xz; echo garb_rc=$?
xz: appended.xz: Unexpected end of input
garb_rc=1
$ xz -dc appended.xz | tail -2
499999
500000
$ cp log.txt.xz b4.xz && printf "ABCD" >> b4.xz && xz -t b4.xz; echo fourbyte_rc=$?
xz: b4.xz: Unexpected end of input
fourbyte_rc=1
$ cp log.txt.xz c4.xz && printf "\0\0\0\0" >> c4.xz && xz -t c4.xz; echo pad_rc=$?
pad_rc=0
解读三组对照:追加 3 字节 XYZ、追加 4 字节 ABCD,-t 都直接判坏(rc=1);追加 4 个 NUL 字节则通过(rc=0)。.xz 格式允许流之后跟「流填充」(stream padding)——必须是 4 字节对齐的全零字节,任何非零尾随数据都过不了 -t;-dc 虽仍能输出完整内容(末两行正确),但 xz 自身退出码为 1(实测 xz -dc a4.xz > /dev/null 返回 1)。对比 gzip(尾部垃圾告警但 rc=2,内容可用)与 bzip2(告警 rc=0),xz 是三者中最严格的。
💡 要点:给
.xz追加任何东西之前想清楚——只有 4 字节对齐的零填充合法。管道拼接多段.xz时,xz 会按多流顺序解压,不需要手工处理衔接。
3.7 -l / -lv 列出压缩文件信息
-l 不解压即可读取 .xz 的流/块元信息:
$ xz -k log.txt
$ xz -l log.txt.xz
Strms Blocks Compressed Uncompressed Ratio Check Filename
1 1 130.7 KiB 3309.5 KiB 0.039 CRC64 log.txt.xz
$ xz -lv log.txt.xz
log.txt.xz (1/1)
Streams: 1
Blocks: 1
Compressed size: 130.7 KiB (133816 B)
Uncompressed size: 3309.5 KiB (3388895 B)
Ratio: 0.039
Check: CRC64
Stream padding: 0 B
Streams:
Stream Blocks CompOffset UncompOffset CompSize UncompSize Ratio Check Padding
1 1 0 0 133816 3388895 0.039 CRC64 0
Blocks:
Stream Block CompOffset UncompOffset TotalSize UncompSize Ratio Check
1 1 12 0 133776 3388895 0.039 CRC64
$ rm -f log.txt.xz
解读:单行模式给出流数、块数、压缩/原始大小、比率与校验类型;-lv 展开到流与块两级——每流的偏移与大小、每块的起始偏移(Block 1 从流内偏移 12 开始,正是 12 字节流头之后)。对比 3.5 节:多线程产物在这里会显示 Blocks=5。-l 是排查「这个 .xz 怎么压的」的第一工具。
3.8 -c 输出到标准输出
-c 把压缩或解压结果写到标准输出,不改动输入文件:
$ xz -c log.txt > stdout.xz
$ ls -l log.txt stdout.xz
-rwxr----- 1 root root 3388895 Oct 15 09:30 log.txt
-rw-r--r-- 1 root root 133816 Oct 15 18:26 stdout.xz
$ xz -dc stdout.xz | tail -2
499999
500000
$ rm -f stdout.xz
解读:xz -c log.txt > stdout.xz 产物与原位压缩等大(133,816 字节),log.txt 原样保留;-dc 接入管道。跨机器传输时 cat data | xz -T0 | ssh 目标 'xz -d > data' 这类流式组合都以 -c 为基础。
3.9 -v 进度显示
-v 输出压缩统计;输出未接终端时打印一行摘要:
$ xz -v -k log.txt
log.txt: 130.7 KiB / 3309.5 KiB = 0.039
$ rm -f log.txt.xz
接终端时显示进度条(用 script 包装修复无终端场景):
$ script -qec "xz -v -k log.txt" /dev/null | tr "\r" "\n"
log.txt (1/1)
100 % 130.7 KiB / 3309.5 KiB = 0.039
$ rm -f log.txt.xz
解读:非终端输出只有最终一行(压缩大小/原始大小/比率);终端下有实时百分比进度。-vv 还会打印每块的网络与内存细节(此处以 -v 为主)。
3.10 -M 内存上限(字典自动降级)
-M 给压缩设置内存用量上限,超限的预设会自动降级字典而不是报错:
$ xz -k -9e -M 200MiB log.txt; echo rc=$?
xz: Adjusted LZMA2 dictionary size from 64 MiB to 16 MiB to not exceed the memory usage limit of 200 MiB
rc=0
$ xz -k -6 -M 200MiB log.txt; echo rc=$?
xz: log.txt.xz: File exists
rc=1
$ ls -l log.txt.xz && rm -f log.txt.xz
-rwxr----- 1 root root 177964 Oct 15 09:30 log.txt.xz
$ xz --info-memory | head -6
Total amount of physical memory (RAM): 40067 MiB (42012700672 B)
Memory usage limit for compression: Disabled
Memory usage limit for decompression: Disabled
解读:第一条命令实测了 -M 的核心机制——-9e 默认 64 MiB 字典,在 200 MiB 上限内被自动调到 16 MiB 并以告警形式说明,压缩照常完成(rc=0,产物 177,964 字节与不带 -M 的 -9e 一致,说明本数据集对字典大小不敏感)。第二条命令的 File exists(rc=1)不是 -M 报错,而是前一条已生成 log.txt.xz、第二条未加 -f 拒绝覆盖——引用时注意区分。--info-memory 可随时查看当前限制状态(实测为 Disabled,即未设限)。
💡 要点:脚本里固定
-M是防 OOM 的好习惯——它不会让压缩失败,而是自动缩小字典,代价是压缩率可能下降。解压端对应的是--memlimit-decompress,超限文件会拒绝解压,7-9 级文件分发给他人前要考虑对方内存。
3.11 文件头 magic number
.xz 流头共 12 字节,用 od 检查:
$ xz -k log.txt
$ od -An -tx1 -N 12 log.txt.xz
fd 37 7a 58 5a 00 00 04 e6 d6 b4 46
$ rm -f log.txt.xz
逐字节解读 fd 37 7a 58 5a 00 00 04 e6 d6 b4 46:
| 字节 | 值 | 含义 |
|---|---|---|
| 1-6 | fd 37 7a 58 5a 00 | magic number,即 FD 37 7A 58 5A 00(.xz 格式身份证,7a 58 5a 是 ASCII "xZ") |
| 7-8 | 00 04 | 流标志:00 为保留字节,04 表示校验类型 4 = CRC64 |
| 9-12 | e6 d6 b4 46 | 流标志的 CRC32 校验 |
解读:与 file 输出的 checksum CRC64 呼应——第 8 字节 04 就是 CRC64 的类型编号(CRC32=1、CRC64=4、SHA-256=10)。前 6 字节是所有 .xz 流的固定开头,可据此快速识别格式。
3.12 目录输入直接跳过
对目录本身执行 xz(不带归档)会被跳过:
$ mkdir -p datadir && cp log.txt datadir/ && xz datadir; echo dir_rc=$?
xz: datadir: Is a directory, skipping
dir_rc=2
$ rm -rf datadir
解读:Is a directory, skipping 退出码 2——xz 与 gzip 一样把目录当「跳过项」而非致命错误(bzip2 则返回 1)。目录压缩归档用 tar cJf(4.3 节)。
四、实战示例
4.1 xzcat / xzgrep:不解压直接检索
$ xz -k log.txt
$ xzcat log.txt.xz | tail -2
499999
500000
$ xzcat log.txt.xz | wc -l
500000
$ xzgrep 49999 log.txt.xz | head -3
49999
149999
249999
$ rm -f log.txt.xz
解读:xzcat 等价于 xz -dc,xzcat | wc -l 确认 500000 行完整;xzgrep 一步完成「解压 + grep」,命中 49999、149999、249999 三行。系统日志轮转产物(如 .xz 后缀的 journal 归档)检索都走这条路。
4.2 不可压数据的压缩天花板
$ xz -k rand.bin
$ ls -l rand.bin rand.bin.xz
-rw-r--r-- 1 root root 1048576 Oct 15 18:26 rand.bin
-rw-r--r-- 1 root root 1048688 Oct 15 18:26 rand.bin.xz
$ rm -f rand.bin.xz
$ xz -k ls.bin
$ ls -l ls.bin ls.bin.xz
-rwxr-xr-x 1 root root 138216 Oct 15 18:26 ls.bin
-rwxr-xr-x 1 root root 51400 Oct 15 18:26 ls.bin.xz
解读:随机数据 rand.bin 压完 1,048,688 字节,仅比原文件大 112 字节——三家对比中头部/块结构开销最小(gzip +187 字节、bzip2 +5,048 字节)。可执行文件 ls.bin 压到 51,400 字节(37.2%),同样优于 gzip 的 58,723 字节与 bzip2 的 58,358 字节。xz 在两类数据上都保持优势,且对不可压数据几乎零惩罚。
4.3 tar 归档配合 xz(tar -J)
tar cJf 打包 + xz 压缩一体化(注意是大写 -J):
$ mkdir -p proj && cp log.txt rand.bin proj/
$ tar cJf proj.tar.xz proj
$ ls -l proj.tar.xz
-rw-r--r-- 1 root root 1272948 Oct 15 18:26 proj.tar.xz
$ xz -l proj.tar.xz
Strms Blocks Compressed Uncompressed Ratio Check Filename
1 1 1243.1 KiB 4340.0 KiB 0.286 CRC64 proj.tar.xz
$ tar tJf proj.tar.xz
proj/
proj/log.txt
proj/rand.bin
$ rm -rf proj proj.tar.xz
解读:proj.tar.xz 为 1,272,948 字节,同一目录 tar 包 gzip 版是 2,119,156 字节、bzip2 版是 1,685,651 字节——xz 版最小。xz -l 直接读出 tar 包的元信息(ratio 0.286);tar tJf 列清单不解压。发布源码包与发行版安装包的常见格式 *.tar.xz 就是这个组合。
4.4 与 gzip / bzip2 的横向对比
在同一环境、同一数据集上对比五组参数(-c 重定向输出,time 计时,实测):
| 数据集 | gzip -6 | gzip -9 | bzip2 -9 | xz -6 | xz -9e |
|---|---|---|---|---|---|
| log.txt(3,388,895 B 文本) | 1,066,382 B / 0.071 s | 1,066,773 B / 0.093 s | 614,325 B / 0.087 s | 133,816 B / 0.791 s | 177,964 B / 1.013 s |
| rand.bin(1,048,576 B 随机) | 1,048,763 B / 0.020 s | 1,048,763 B / 0.021 s | 1,053,788 B / 0.066 s | 1,048,688 B / 0.165 s | 1,048,688 B / 0.205 s |
| ls.bin(138,216 B 可执行) | 58,723 B / 0.005 s | 58,597 B / 0.016 s | 58,358 B / 0.006 s | 51,400 B / 0.032 s | 51,452 B / 0.063 s |
结论(基于上表实测值):
- 压缩率:xz ≪ bzip2 < gzip。log.txt 上 xz -6(133,816 B)只有 gzip -6 的 12.5%、bzip2 -9 的 21.8%。
- 耗时:gzip(0.071 s)最快,bzip2(0.087 s)同量级,xz(0.791 s)慢约 11 倍——xz 的压缩率是用 CPU 时间换的;大文件可叠加
-T0回收大量时间(3.5 节实测 3.3 倍加速)。 - 「高级别更小」在三家都不成立:gzip -9 反超 gzip -6、bzip2 本数据集级别越高越大(3.5 节)、xz -9e 比 -6 大 33%;xz 全场最小的是
-5(47,856 字节,3.4 节)。 - 不可压数据开销:xz +112 B < gzip +187 B ≪ bzip2 +5,212 B。
- 选型建议:交互式/高频操作选 gzip;体积敏感的中等负载选 bzip2;归档、分发类一次性压缩选 xz(配
-T0),并按 3.4 节实测几个级别再定参。
五、注意事项与常见问题
Q1:xz 的默认级别是多少?-9e 一定最好吗?
默认 -6。-9e 不保证最小——3.4 节实测它比 -6 大 33%(177,964 对 133,816 字节),全场最小的是 -5。级别是字典与匹配器参数的组合,必须对代表性数据实测。
Q2:为什么帮助里特别警告 7-9 级的内存?
级别越高字典越大(-9 默认 64 MiB),压缩端要一份、解压端也要一份。低内存设备解压 7-9 级文件可能直接失败;给别人的分发包建议不超过 6 级,或明确告知内存要求。压缩端可用 -M 限制(3.10 节实测会自动降级字典并告警)。
Q3:多线程压缩怎么开?有什么代价?
xz -T0 用满全部核心(3.5 节实测 12 核环境 3.3 倍加速,产物还更小)。代价是内存按线程数放大(每线程一份字典),低内存运行环境改用 -T 线程数 或配合 -M;小文件没必要开。
Q4:怎么制造一个「真的坏了」的 .xz 来测试 -t?
用 head -c N 截断时 N 必须小于压缩文件实际大小——N 大于文件大小时得到的是完整副本,-t 照样通过(3.6 节实测踩坑记录)。真实截断报 Unexpected end of input、rc=1。
Q5:往 .xz 文件末尾追加数据会怎样?
gzip/bzip2 只是告警,xz 直接判坏:任何非零尾随字节(3 字节 XYZ、4 字节 ABCD 实测)都让 -t 返回 rc=1;只有 4 字节对齐的全零「流填充」合法(rc=0)。-dc 虽能输出完整内容但退出码也是 1(3.6 节三组对照实测)。
Q6:xz -d -k 报 File exists 怎么办?
解压目标已存在时 xz 拒绝覆盖(rc=1),确认后加 -f(3.2 节)。与 gzip 的 already exists; not overwritten(rc=2)措辞和退出码都不同,跨格式脚本注意分支条件。
Q7:.xz、.tar.xz、.txz 是什么关系?
.xz 是单文件压缩流;.tar.xz(.txz 是别名)是 tar 打包后整体经 xz 压缩,用 tar cJf/tJf/xJf 操作(4.3 节)。xz -l 对两类文件都能读出流/块信息。
六、参考链接
- XZ Utils 官方主页:https://tukaani.org/xz/
- .xz 文件格式规范(流/块/校验的权威定义):https://tukaani.org/xz/format.html
- xz(1) 手册页(man7.org):https://man7.org/linux/man-pages/man1/xz.1.html
- XZ Utils GitHub 仓库:https://github.com/tukaani-project/xz
- LZMA SDK 背景(LZMA 算法出处):https://www.7-zip.org/sdk.html