xz, unxz, xzcat, lzma, unlzma, lzcat - 压缩或解压缩 .xz 和 .lzma 文件
概要
xz [选项...] [文件...]
命令别名
unxz 等同于 xz --解压缩。
xzcat 等同于 xz --解压缩 --标准输出。
lzma 等同于 xz --格式=lzma。
unlzma 等同于 xz --格式=lzma --解压缩。
lzcat 等同于 xz --格式=lzma --解压缩 --标准输出。
在编写需要解压缩文件的脚本时,建议始终使用 xz 命令,并带有适当的参数(xz -d 或 xz -dc),而不是使用 unxz 和 xzcat 命令。
描述
xz 是一种通用的数据压缩工具,其命令行语法类似于 gzip(1) 和 bzip2(1)。原生文件格式是 .xz 格式,但 LZMA Utils 中使用的旧版 .lzma 格式以及没有容器格式标头的原始压缩流也受支持。此外,还支持 lzip 使用的 .lz 格式的解压缩。
xz 根据所选的操作模式压缩或解压缩每个文件。如果没有提供文件,或者文件是 -,则 xz 从标准输入读取,并将处理后的数据写入标准输出。如果标准输出是终端,xz 将拒绝(显示错误并跳过该文件)将压缩数据写入标准输出。同样,如果标准输入是终端,xz 将拒绝从标准输入读取压缩数据。
除非指定 --标准输出,否则 xz 会显示警告并跳过任何以下情况的文件:
文件不是常规文件。不会跟随符号链接,因此符号链接不被视为常规文件。
文件具有多个硬链接。
文件设置了 setuid、setgid 或 sticky 位。
操作模式设置为压缩,并且文件已经具有目标文件格式的后缀(.xz 或 .lzma,用于压缩为 .xz 格式,以及 .lzma 或 .tlz,用于压缩为 .lzma 格式)。
操作模式设置为解压缩,并且文件不具有任何受支持的文件格式的后缀(.xz、.txz、.lzma、.tlz 或 .lz)。
成功压缩或解压缩文件后,xz 会将所有者、组、权限、访问时间和修改时间从源文件复制到目标文件。如果复制组失败,权限将被修改,以防止目标文件对那些没有权限访问源文件的用户变得可访问。xz 尚未支持复制其他元数据,如访问控制列表或扩展属性。
目标文件成功关闭后,除非指定了 --keep 标志,否则源文件将被删除。如果输出写入标准输出,或者发生错误,则永远不会删除源文件。
向 xz 进程发送 SIGINFO 或 SIGUSR1 信号,会使其将进度信息打印到标准错误。这只有有限的用途,因为当标准错误是终端时,使用 --verbose 将显示自动更新的进度指示器。
内存使用情况
xz 的内存使用量从几百千字节到几千兆字节不等,具体取决于压缩设置。用于压缩文件的设置决定了解压缩器的内存需求。通常,解压缩器需要的内存是压缩器在创建文件时所需内存的 5% 到 20%。例如,当前使用 xz -9 创建的文件需要 65 MB 的内存才能解压缩。但是,也可能存在需要几千兆字节内存才能解压缩的 .xz 文件。
特别是旧系统的用户可能会发现非常大的内存使用令人讨厌。为了防止出现不愉快的意外,xz 具有内置的内存使用量限制器,默认情况下已禁用。虽然某些操作系统提供了一种限制进程内存使用量的方法,但依赖它被认为不够灵活(例如,使用 ulimit(1) 限制虚拟内存往往会严重影响 mmap(2))。
可以使用命令行选项 --memlimit=limit 启用内存使用量限制器。通常,通过设置环境变量 XZ_DEFAULTS,可以更方便地默认启用限制器,例如 XZ_DEFAULTS=--memlimit=150MiB。 可以通过使用 --memlimit-compress=limit 和 --memlimit-decompress=limit 分别为压缩和解压缩设置限制。 在 XZ_DEFAULTS 之外使用这两个选项很少有用,因为 xz 的单个运行无法同时进行压缩和解压缩,并且 --memlimit=limit(或 -M limit)在命令行中输入起来更短。
如果解压缩时超过指定的内存使用量限制,xz 将显示错误并且解压缩文件将失败。如果压缩时超过限制,xz 将尝试缩放设置,以便不再超过限制(在使用 --format=raw 或 --no-adjust 时除外)。 这样,除非限制非常小,否则操作不会失败。 对设置的缩放以不与压缩级别预设匹配的步骤进行,例如,如果限制仅略低于 xz -9 所需的内存量,则设置将只会略微缩小,而不是全部缩小到 xz -8。
.xz 文件的连接和填充
可以将 .xz 文件直接连接。xz 会像这些文件是一个单独的 .xz 文件一样对其进行解压缩。
可以在连接的部分之间或在最后一个部分之后插入填充。填充必须由空字节组成,并且填充的大小必须是四字节的倍数。例如,如果 .xz 文件存储在测量文件大小为 512 字节块的介质上,这可能很有用。
不允许对 .lzma 文件或原始数据流进行连接和填充。
选项
整数后缀和特殊值
在大多数需要整数参数的地方,都支持可选的后缀,以便轻松指示较大的整数。整数和后缀之间不能有空格。
KiB 将整数乘以 1,024 (2^10)。Ki、k、kB、K 和 KB 都可作为 KiB 的同义词。 MiB 将整数乘以 1,048,576 (2^20)。Mi、m、M 和 MB 都可作为 MiB 的同义词。 GiB 将整数乘以 1,073,741,824 (2^30)。Gi、g、G 和 GB 都可作为 GiB 的同义词。
特殊值 max 可用于指示该选项支持的最大整数值。
操作模式
如果提供了多个操作模式选项,则最后一个选项生效。
-z, --compress
压缩。这是默认操作模式,当未指定任何操作模式选项并且没有其他操作模式从命令名称推断得出时(例如,unxz 意味着 --decompress)。
成功压缩后,除非写入标准输出或指定了 --keep,否则将删除源文件。
-d, --decompress, --uncompress
解压缩。成功解压缩后,除非写入标准输出或指定了 --keep,否则将删除源文件。
-t, --test
测试压缩文件的完整性。此选项等效于 --decompress --stdout,除了解压缩的数据将被丢弃而不是写入标准输出。不会创建或删除任何文件。
-l, --list
打印有关压缩文件的信息。不会产生任何解压缩的输出,也不会创建或删除任何文件。在列表模式下,程序无法从标准输入或其他不可寻址的来源读取压缩数据。
默认列表显示有关文件的基本信息,每行一个文件。要获取更多详细信息,请也使用 --verbose 选项。对于更多信息,可以使用 --verbose 两次,但请注意,这可能会很慢,因为获取所有额外信息需要进行多次寻道。详细输出的宽度超过 80 个字符,因此将输出管道传输到例如 less -S 可能很方便,如果终端的宽度不够。
确切的输出可能因 xz 版本和不同的语言环境而异。对于机器可读的输出,应使用 --robot --list。
操作修改器
-k, --keep
不要删除输入文件。
从 xz 5.2.6 开始,此选项还会使 xz 压缩或解压缩,即使输入是符号链接到普通文件,具有多个硬链接,或者设置了 setuid、setgid 或 sticky 位。setuid、setgid 和 sticky 位不会复制到目标文件。在早期版本中,这仅在 --force 选项下进行。
-f, --force
此选项有几个效果:
如果目标文件已存在,则在压缩或解压缩之前将其删除。
即使输入是符号链接到普通文件,具有多个硬链接,或者设置了 setuid、setgid 或 sticky 位,也可以进行压缩或解压缩。setuid、setgid 和 sticky 位不会复制到目标文件。
与 --decompress --stdout 一起使用,并且当 xz 无法识别源文件类型时,将源文件按原样复制到标准输出。这允许 xzcat --force 像 [cat]({filename}../../cat)(1) 一样使用,用于未用 xz 压缩的文件。请注意,将来,xz 可能会支持新的压缩文件格式,这可能会使 xz 解压缩更多类型的文件,而不是将它们按原样复制到标准输出。可以使用 --format=format 来限制 xz 仅解压缩单个文件格式。
-c, --stdout, --to-stdout
将压缩或解压缩的数据写入标准输出而不是文件。这表示 --keep。
--single-stream
仅解压缩第一个 .xz 流,并忽略可能存在的后续输入数据。通常,此类尾部垃圾数据会导致 xz 显示错误。
xz 从不解压缩 .lzma 文件或原始流中的多个流,但此选项仍然使 xz 忽略 .lzma 文件或原始流之后的可能存在的尾部数据。
如果操作模式不是 --decompress 或 --test,则此选项无效。
从 xz 5.7.1alpha 开始,--single-stream 表示 --keep。
--no-sparse
禁用创建稀疏文件。默认情况下,如果解压缩到普通文件,xz 会尝试创建稀疏文件,如果解压缩的数据包含长序列的二进制零。只要标准输出连接到普通文件,并且满足某些其他条件以使其安全,它也可以在写入标准输出时工作。创建稀疏文件可以节省磁盘空间并加快解压缩速度,从而减少磁盘 I/O。
-S .suf, --suffix=.suf
在压缩时,使用 .suf 作为目标文件的后缀,而不是 .xz 或 .lzma。如果未写入标准输出并且源文件已具有 .suf 后缀,则会显示警告并且跳过该文件。
在解压缩时,除了 .xz、.txz、.lzma、.tlz 或 .lz 后缀之外,还会识别具有 .suf 后缀的文件。如果源文件具有 .suf 后缀,则会删除该后缀以获取目标文件名。
当压缩或解压缩原始流(--format=raw)时,除非写入标准输出,否则必须始终指定后缀,因为对于原始流没有默认后缀。
--files[=file]
从文件中读取要处理的文件名;如果省略文件,则从标准输入读取文件名。文件名必须以换行符结尾。短横线 (-) 被视为普通文件名;它不表示标准输入。如果命令行参数中也给出了文件名,则在读取文件中的文件名之前先处理这些文件名。
--files0[=file]
这与 --files[=file] 相同,只是每个文件名必须以空字符结尾。
基本文件格式和压缩选项
-F format, --format=format
指定要压缩或解压缩的文件格式:
auto 这是默认值。在压缩时,auto 等效于 xz。在解压缩时,自动检测输入文件的格式。请注意,原始流(使用 --format=raw 创建)无法自动检测。
xz 压缩为 .xz 文件格式,或在解压缩时仅接受 .xz 文件。
lzma, alone
压缩为旧的 .lzma 文件格式,或在解压缩时仅接受 .lzma 文件。备用名称 alone 仅为了与 LZMA Utils 保持向后兼容。
lzip 在解压缩时仅接受 .lz 文件。不支持压缩。
.lz 格式版本 0 和 1 均受支持。版本 0 文件由 lzip 1.3 及更早版本生成。此类文件并不常见,但可能在文件存档中找到,因为一些源代码包以这种格式发布。人们可能也有旧的个人文件以这种格式存储。lzip 1.18 中删除了对格式版本 0 的解压缩支持。lzip 1.4 及更高版本创建版本 1 格式的文件。
raw 压缩或解压缩原始流(无标题)。这仅供高级用户使用。要解码原始流,需要使用 --format=raw 并显式指定筛选器链,而通常这些内容会存储在容器标题中。
-C check, --check=check
指定完整性检查的类型。从解压缩的数据中计算检查结果,并将其存储在 .xz 文件中。此选项仅在压缩为 .xz 格式时有效;.lzma 格式不支持完整性检查。如果存在完整性检查,则在解压缩 .xz 文件时会对其进行验证。
支持的检查类型:
none 根本不计算完整性检查。通常这是一个坏主意。这在数据完整性已通过其他方式验证时可能有用。
crc32 使用 IEEE-802.3(以太网)中的多项式计算 CRC32。
crc64 使用 ECMA-182 中的多项式计算 CRC64。这是默认值,因为它比 CRC32 更好地检测损坏的文件,并且速度差异可以忽略不计。
sha256 计算 SHA-256。这比 CRC32 和 CRC64 慢一些。
.xz 文件的完整性始终使用 CRC32 进行验证。无法更改或禁用它。
--ignore-check
在解压缩时,不要验证压缩数据的完整性检查。 .xz 文件头中的 CRC32 值仍会正常验证。
除非您知道自己在做什么,否则请勿使用此选项。使用此选项的可能原因:
尝试从损坏的 .xz 文件中恢复数据。 加快解压缩速度。这在 SHA-256 或压缩效果极佳的文件中最为重要。除非以其他方式对文件完整性进行外部验证,否则不建议将此选项用于此目的。
-0 ... -9
选择压缩预设级别。默认值为 -6。如果指定了多个预设级别,则最后一个级别生效。如果已经指定了自定义滤器链,则设置压缩预设级别会清除自定义滤器链。
这些预设之间的差异比 gzip(1) 和 bzip2(1) 之间的差异更大。 所选的压缩设置决定了解压缩器的内存需求,因此使用过高的预设级别可能会导致在旧系统上解压缩文件时出现问题,因为旧系统具有较少的 RAM。特别是,像使用 gzip(1) 和 bzip2(1) 那样盲目地使用 -9 并不是一个好主意。
-0 ... -3
这些是相对较快的预设。-0 在压缩时,有时比 gzip -9 更快,而且压缩效果更好。较高的预设通常具有与 bzip2(1) 相当的压缩速度,并且具有可比或更好的压缩比,尽管结果在很大程度上取决于正在压缩的数据类型。
-4 ... -6
提供良好的压缩效果,同时保持解压缩器的内存使用量在合理水平,即使对于旧系统也是如此。-6 是默认值,通常是分发即使在只有 16 MiB RAM 的系统上也可以解压缩的文件的一个不错的选择。(-5e 或 -6e 可能值得考虑。请参阅 --extreme。)
-7 ... -9
这些与 -6 类似,但具有更高的压缩器和解压缩器内存需求。这些只有在压缩大于 8 MiB、16 MiB 和 32 MiB 的文件时才有用。
在相同的硬件上,解压缩速度大约是每秒恒定数量的压缩数据。换句话说,压缩效果越好,解压缩速度通常越快。这意味着每秒可以生成的未压缩输出量可能会有很大差异。
以下表格总结了预设的特征:
Preset DictSize CompCPU CompMem DecMem -0 256 KiB 0 3 MiB 1 MiB -1 1 MiB 1 9 MiB 2 MiB -2 2 MiB 2 17 MiB 3 MiB -3 4 MiB 3 32 MiB 5 MiB -4 4 MiB 4 48 MiB 5 MiB -5 8 MiB 5 94 MiB 9 MiB -6 8 MiB 6 94 MiB 9 MiB -7 16 MiB 6 186 MiB 17 MiB -8 32 MiB 6 370 MiB 33 MiB -9 64 MiB 6 674 MiB 65 MiB
列描述:
DictSize 是 LZMA2 字典大小。使用大于未压缩文件大小的字典会浪费内存。因此,在没有真正需要的情况下,最好避免使用 -7 到 -9 预设。在 -6 及更低级别时,浪费的内存通常不多,可以忽略不计。
CompCPU 是一个简化了的 LZMA2 设置,它会影响压缩速度。字典大小也会影响速度,因此,虽然 -6 到 -9 的 CompCPU 相同,但较高级别通常会稍微慢一些。要获得更慢的速度,从而可能获得更好的压缩效果,请参阅 --extreme。
CompMem 包含单线程模式下压缩器的内存需求。它在不同的 xz 版本之间可能会略有不同。
DecMem 包含解压缩器的内存需求。也就是说,压缩设置决定了解压缩器的内存需求。确切的解压缩器内存使用量略大于 LZMA2 字典大小,但表格中的值已向上取整到下一个完整的 MiB。
多线程模式的内存需求远高于单线程模式。使用默认的 --block-size 值,每个线程需要 3*3*DictSize 加上 CompMem 或 DecMem。例如,使用 -6 预设的四个线程需要 660–670 MiB 内存。
-e, --extreme
使用所选压缩预设级别的更慢变体(-0 到 -9),希望获得更好的压缩比,但运气不好的情况下,这也会导致压缩效果变差。解压缩器的内存使用量不受影响,但在 -0 到 -3 预设级别,压缩器的内存使用量会略有增加。
由于有两个字典大小为 4 MiB 和 8 MiB 的预设,-3e 和 -5e 预设使用比 -4e 和 -6e 预设稍快的设置(较低的 CompCPU)。这样,就不会有两个预设完全相同。
预设 DictSize CompCPU CompMem DecMem -0e 256 KiB 8 4 MiB 1 MiB -1e 1 MiB 8 13 MiB 2 MiB -2e 2 MiB 8 25 MiB 3 MiB -3e 4 MiB 7 48 MiB 5 MiB -4e 4 MiB 8 48 MiB 5 MiB -5e 8 MiB 7 94 MiB 9 MiB -6e 8 MiB 8 94 MiB 9 MiB -7e 16 MiB 8 186 MiB 17 MiB -8e 32 MiB 8 370 MiB 33 MiB -9e 64 MiB 8 674 MiB 65 MiB
例如,总共有四个使用 8 MiB 字典的预设,它们的顺序从最快到最慢是 -5、-6、-5e 和 -6e。
--fast
--best 这些是 -0 和 -9 的一些具有误导性的别名。这些选项仅用于与 LZMA Utils 保持向后兼容。请避免使用这些选项。
--block-size=size
在压缩为 .xz 格式时,将输入数据分割为大小为 size 字节的块。这些块独立于彼此进行压缩,这有助于多线程处理,并实现有限的随机访问解压缩。此选项通常用于在多线程模式下覆盖默认块大小,但此选项也可以在单线程模式下使用。
在多线程模式下,每个线程会分配大约三倍大小的字节数用于缓冲输入和输出。默认大小是三倍的 LZMA2 字典大小或 1MiB,取两者中的较大值。通常,一个好的值是 2–4 倍的 LZMA2 字典大小,或者至少 1 MiB。使用小于 LZMA2 字典大小的值会浪费 RAM,因为 LZMA2 字典缓冲区将无法完全使用。在多线程模式下,块的大小存储在块头中。此大小信息对于多线程解压缩是必需的。
在单线程模式下,默认情况下不进行块分割。设置此选项不会影响内存使用。块头中不存储任何大小信息,因此在单线程模式下创建的文件与在多线程模式下创建的文件不会相同。缺乏大小信息也意味着 xz 将无法在多线程模式下解压缩这些文件。
^ -block-list=items
在压缩为 .xz 格式时,在给定的未压缩数据间隔之后,使用可选的自定义过滤器链开始一个新的块。
^ tems 是一个逗号分隔的列表。每个项目由一个可选的过滤器链编号(介于 0 到 9 之间)组成,后跟一个冒号 (:),以及一个必需的未压缩数据大小。省略一个项目(两个或多个连续的逗号)是使用前一个项目的大小和过滤器的一种简写。
如果输入文件大于 items 中大小的总和,则会重复最后一个项目,直到文件结束。可以使用特殊值 0 作为最后一个大小,以指示应将文件的其余部分编码为单个块。
可以与 --filters1=filters ... --filters9=filters 选项结合使用,为每个块指定替代的过滤器链。这些选项定义了具有 1 到 9 之间的标识符的过滤器链。过滤器链 0 可用于引用默认过滤器链,这与不指定过滤器链相同。过滤器链标识符可以在未压缩大小之前使用,后跟一个冒号 (:)。例如,如果指定 --block-list=1:2MiB,3:2MiB,2:4MiB,,2MiB,0:4MiB,则将使用以下方法创建块:
由 --filters1 指定的过滤器链和 2 MiB 输入
由 --filters3 指定的过滤器链和 2 MiB 输入
由 --filters2 指定的过滤器链和 4 MiB 输入
由 --filters2 指定的过滤器链和 4 MiB 输入
默认过滤器链和 2 MiB 输入
默认过滤器链和 4 MiB 输入,用于每个块直到输入结束。
如果指定的大小超过编码器的块大小(无论是多线程模式下的默认值,还是通过 --block-size=size 指定的值),编码器将在保持 items 中指定的边界的同时创建额外的块。例如,如果指定 --block-size=10MiB --block-list=5MiB,10MiB,8MiB,12MiB,24MiB 且输入文件为 80 MiB,则将获得 11 个块:5, 10, 8, 10, 2, 10, 10, 4, 10, 10 和 1 MiB。
在多线程模式下,块的大小存储在块头中。 在单线程模式下,不会这样做,因此编码后的输出与多线程模式的输出不相同。
--flush-timeout=timeout
在压缩时,如果自上次刷新以来,已经超过 timeout 毫秒(一个正整数),并且读取更多输入会阻塞,则所有待处理的输入数据都会从编码器中刷新,并使其在输出流中可用。如果 xz 用于压缩通过网络传输的数据,这会很有用。较小的 timeout 值会在接收端以较小的延迟提供数据,但较大的 timeout 值可以提供更好的压缩比。
此功能默认禁用。如果多次指定此选项,则以最后一次指定为准。特殊的 timeout 值为 0 可用于显式禁用此功能。
此功能在非 POSIX 系统上不可用。
此功能仍然是实验性的。目前,由于 xz 的缓冲方式,xz 不适合用于实时解压缩流。
--no-sync
在删除源文件之前,不要将目标文件及其目录与存储设备同步。如果压缩或解压缩许多小文件,这可以提高性能。但是,如果系统在删除操作之后不久崩溃,则可能目标文件未写入存储设备,但已删除源文件。在这种情况下,原始源文件和目标文件都不可用。
此选项仅在 xz 将要删除源文件时才有效。在其他情况下,不会进行同步。
同步和 --no-sync 是在 xz 5.7.1alpha 中添加的。
--memlimit-compress=limit
设置压缩过程的内存使用限制。如果多次指定此选项,则以最后一次指定为准。
如果压缩设置超过限制,xz 将尝试向下调整设置,以使其不再超过限制,并显示一条通知,说明已进行自动调整。调整的顺序如下:减少线程数、如果即使单个线程在多线程模式下超过限制,则切换到单线程模式,最后减少 LZMA2 字典大小。
使用 --format=raw 或如果已指定 --no-adjust,则只能减少线程数,因为这可以在不影响压缩输出的情况下完成。
如果即使使用上述调整也无法满足限制,则会显示错误消息,并且 xz 将退出,退出状态为 1。
限制可以以多种方式指定:
限制可以是一个以字节为单位的绝对值。使用像 MiB 这样的整数后缀可能会很有用。例如:--memlimit-compress=80MiB
限制可以指定为总物理内存(RAM)的百分比。这在设置 shell 初始化脚本中的 XZ_DEFAULTS 环境变量时特别有用,该脚本在不同的计算机之间共享。这样,限制会根据系统内存大小自动调整。例如:--memlimit-compress=70%
可以通过将其设置为 0 来重置限制,使其恢复到默认值。目前,这等同于将限制设置为最大值(无内存使用限制)。
对于 32 位 xz,有一个特殊情况:如果限制将超过 4020 MiB,则该限制将设置为 4020 MiB。在 MIPS32 上,则使用 2000 MiB。 (0 和 max 值不受此影响。 类似的功能不适用于解压缩。)这在 32 位可执行文件可以访问 4 GiB 地址空间(MIPS32 上的 2 GiB)时可能会有所帮助,同时希望在其他情况下不会造成损害。
请参阅“内存使用”部分。
^ -memlimit-decompress=limit
设置解压缩的内存使用限制。 这也会影响 --list 模式。 如果操作在不超出限制的情况下不可行,xz 将显示错误,并且解压缩文件将失败。 请参阅 --memlimit-compress=limit,了解指定限制的可能方法。
^ -memlimit-mt-decompress=limit
设置多线程解压缩的内存使用限制。 这只会影响线程数;这绝不会导致 xz 拒绝解压缩文件。 如果限制过低,无法允许任何多线程,则该限制将被忽略,并且 xz 将继续以单线程模式运行。 请注意,如果同时使用 --memlimit-decompress,它将始终应用于单线程和多线程模式,因此多线程的有效限制将永远不会高于通过 --memlimit-decompress 设置的限制。
与其他内存使用限制选项相比,--memlimit-mt-decompress=limit 具有系统特定的默认限制。 可以使用 xz --info-memory 查看当前值。
此选项及其默认值存在的原因是,如果没有限制,多线程解压缩器可能会为某些输入文件分配大量的内存。 如果您的系统上的默认限制过低,请随时增加该限制,但切勿将其设置为大于可用 RAM 的值,因为在适当的输入文件下,xz 将尝试使用该数量的内存,即使线程数量很少。 耗尽内存或进行交换不会提高解压缩性能。
请参阅 --memlimit-compress=limit,了解指定限制的可能方法。 将限制设置为 0 会将限制重置为系统特定的默认值。
^ M limit, --memlimit=limit, --memory=limit
这等效于指定 --memlimit-compress=limit --memlimit-decompress=limit --memlimit-mt-decompress=limit。
--no-adjust
如果无法在不调整影响压缩输出的设置的情况下满足内存使用限制,则显示错误并退出。 也就是说,这可以防止 xz 将编码器从多线程模式切换到单线程模式,并防止减小 LZMA2 字典大小。 即使使用了此选项,如果这样做不会影响压缩输出,线程数也可能会减少以满足内存使用限制。
创建原始流时,始终禁用自动调整 (--format=raw)。
-T threads, --threads=threads
指定要使用的工作线程数。 将线程设置为特殊值 0 会使 xz 使用与系统中的处理器数量一样多的线程。 实际线程数可能少于线程数,如果输入文件对于给定设置的线程来说太小,或者使用更多线程会超过内存使用限制,则会发生这种情况。
单线程和多线程压缩器产生不同的输出。 单线程压缩器将产生最小的文件大小,但只有多线程压缩器的输出才能使用多个线程进行解压缩。 将线程设置为 1 将使用单线程模式。 将线程设置为任何其他值,包括 0,将使用多线程压缩器,即使系统仅支持一个硬件线程也是如此。(xz 2.x 在这种情况下使用单线程模式。)
要仅使用一个线程使用多线程模式,请将线程设置为 +1。 + 前缀对其他值没有影响。 内存使用限制仍然可能导致 xz 切换到单线程模式,除非使用 --no-adjust。 在 xz 5.4.0 中添加了对 + 前缀的支持。
如果请求了自动线程数,并且未指定内存使用限制,则将使用特定于系统的默认软限制来可能限制线程数。 从某种意义上说,这是一个软限制,即如果线程数变为 1,则会忽略它,因此软限制永远不会阻止 xz 进行压缩或解压缩。 此默认软限制不会使 xz 从多线程模式切换到单线程模式。 可以使用 xz --info-memory 查看活动限制。
当前唯一的线程方法是将输入分成块并独立压缩它们。 默认块大小取决于压缩级别,并且可以使用 --block-size=size 选项进行覆盖。
线程解压缩仅适用于包含多个块的文件,这些块在块标头中包含大小信息。 足够大的所有在多线程模式下压缩的文件都满足此条件,但即使使用了 --block-size=size,在单线程模式下压缩的文件也不满足此条件。
线程的默认值为 0。 在 xz 5.4.x 及更早版本中,默认值为 1。
自定义压缩器过滤器链
自定义过滤器链允许详细指定压缩设置,而不是依赖于与预设关联的设置。 当指定自定义过滤器链时,之前在命令行中指定的预设选项(-0 ... -9 和 --extreme)将被忽略。 如果在指定一个或多个自定义过滤器链选项之后指定了一个预设选项,则新的预设生效,并且之前指定的自定义过滤器链选项将被忽略。
一个过滤器链类似于命令行中的管道。在压缩时,未压缩的输入会传递到第一个过滤器,其输出会传递到下一个过滤器(如果有)。最后一个过滤器的输出将被写入压缩的文件。链中的最大过滤器数量为四个,但通常过滤器链只有一到两个过滤器。
许多过滤器在过滤器链中的位置都有局限性:有些过滤器只能作为链中的最后一个过滤器工作,有些过滤器只能作为非最后一个过滤器工作,有些过滤器可以在链中的任何位置工作。根据过滤器,这种限制要么是过滤器设计固有的,要么是为了防止安全问题。
可以使用两种不同的方式指定自定义过滤器链。`--filters=filters` 和 `--filters1=filters ... --filters9=filters` 选项允许使用 liblzma 过滤器字符串语法,在一个选项中指定整个过滤器链。或者,可以通过使用一个或多个单独的过滤器选项来指定过滤器链,这些选项的顺序应与所需的过滤器链顺序相同。也就是说,单独的过滤器选项的顺序很重要!在解码原始流(`--format=raw`)时,过滤器链必须以与压缩时指定的相同顺序进行指定。在完整的链选项(`--filters=filters`)之前指定的任何单独的过滤器或预设选项都将被忽略。在完整的链选项之后指定的单独的过滤器将重置过滤器链。
完整选项和单独的过滤器选项都接受特定于过滤器的选项,这些选项以逗号分隔的列表形式提供。选项中的多余逗号将被忽略。每个选项都有一个默认值,因此只需指定要更改的选项。
要查看完整的过滤器链和选项,请使用 `xz -vv`(即,两次使用 `--verbose`)。这也可以用于查看预设使用的过滤器链选项。
`--filters=filters`
指定完整的过滤器链或单个预设。每个过滤器可以用空格或两个连字符(`--`)分隔。`filters` 可能需要在 shell 命令行中用引号引起来,以便将其解析为单个选项。要指定选项,请使用 `:` 或 `=`。预设可以以 `-` 为前缀,后跟零个或多个标志。唯一支持的标志是 `e`,用于应用与 `--extreme` 相同的选项。
`--filters1=filters ... --filters9=filters`
指定最多九个额外的过滤器链,这些链可以与 `--block-list` 一起使用。
例如,在压缩包含可执行文件后跟文本文件的存档时,可执行部分可以使用包含 BCJ 过滤器的过滤器链,而文本部分仅使用 LZMA2 过滤器。
--filters-help
显示帮助消息,描述如何指定预设和自定义过滤器链,方法是在 `--filters` 和 `--filters1=filters ... --filters9=filters` 选项中进行指定,然后成功退出。
--lzma1[=options]
--lzma2[=options]
将 LZMA1 或 LZMA2 过滤器添加到过滤器链中。这些过滤器只能作为链中的最后一个过滤器使用。
LZMA1 是一种遗留过滤器,主要出于对遗留 .lzma 文件格式的支持而保留,因为该格式仅支持 LZMA1。LZMA2 是 LZMA1 的更新版本,用于解决 LZMA1 的一些实际问题。.xz 格式使用 LZMA2,并且完全不支持 LZMA1。LZMA1 和 LZMA2 的压缩速度和压缩率在实践中几乎相同。
LZMA1 和 LZMA2 共享相同的选项集:
preset=preset
将所有 LZMA1 或 LZMA2 选项重置为预设。预设由一个整数组成,后面可以跟一个单字母的预设修饰符。整数可以是 0 到 9,对应于命令行选项 -0 ... -9。目前仅支持一个修饰符,即 e,对应于 --extreme。如果未指定预设,则 LZMA1 或 LZMA2 选项将采用默认值(预设为 6)。
dict=size
字典(历史缓冲区)大小表示保留在内存中的最近处理的未压缩数据的字节数。该算法尝试在未压缩的数据中查找重复的字节序列(匹配项),并将其替换为对当前在字典中的数据的引用。字典越大,找到匹配项的可能性就越大。因此,增加字典大小通常可以提高压缩率,但大于未压缩文件大小的字典会浪费内存。
典型的字典大小为 64 KiB 到 64 MiB。最小值为 4 KiB。当前,压缩的字典最大值为 1.5 GiB(1536 MiB)。解压缩器已经支持最大为 4 GiB 减 1 字节的字典,这是 LZMA1 和 LZMA2 流格式的最大值。
字典大小和匹配查找器 (mf) 一起决定了 LZMA1 或 LZMA2 编码器的内存使用量。用于解压缩的字典大小必须与压缩时使用的字典大小相同(或更大),因此解压缩器的内存使用量由压缩时使用的字典大小决定。.xz 标头将字典大小存储为 2^n 或 2^n + 2^(n-1),因此这些大小在压缩时略受青睐。其他大小在存储到 .xz 标头中时会被向上舍入。
lc=lc
指定字面上下文位的数量。最小值为 0,最大值为 4;默认值为 3。此外,lc 和 lp 的总和不能超过 4。
所有无法编码为匹配项的字节都编码为字面量。也就是说,字面量只是一个一个编码的 8 位字节。
字面量编码假设前一个未压缩字节的最高 lc 位与下一个字节相关。例如,在典型的英语文本中,大写字母通常后跟小写字母,小写字母通常后跟另一个小写字母。在 US-ASCII 字符集中,最高三位是对于大写字母为 010,对于小写字母为 011。当 lc 至少为 3 时,字面量编码可以利用未压缩数据中的此属性。
默认值 (3) 通常效果良好。 如果需要最大压缩率,请测试 lc=4。 有时会略有帮助,有时则会降低压缩率。 如果降低了压缩率,请同时测试 lc=2。
lp=lp 指定字面位置位的数量。 最小值是 0,最大值是 4,默认值是 0。
Lp 影响在编码字面值时,假设的未压缩数据中的对齐方式。 有关更多信息,请参阅 pb。
pb=pb 指定位置位的数量。 最小值是 0,最大值是 4;默认值是 2。
Pb 影响在一般情况下,假设的未压缩数据中的对齐方式。 默认值表示四字节对齐 (2^pb=2^2=4),这通常是一个不错的选择,尤其是在没有更好的猜测时。
当已知对齐方式时,相应地设置 pb 可能会略微减小文件大小。 例如,对于具有一字节对齐方式的文本文件(US-ASCII、ISO-8859-*、UTF-8),将 pb 设置为 0 可以稍微提高压缩率。 对于 UTF-16 文本,pb=1 是一个不错的选择。 如果对齐方式是奇数,例如 3 字节,那么 pb=0 可能是最佳选择。
即使可以使用 pb 和 lp 调整假设的对齐方式,LZMA1 和 LZMA2 仍然略微偏向于 16 字节对齐。 在设计可能经常使用 LZMA1 或 LZMA2 进行压缩的文件格式时,可能值得考虑这一点。
mf=mf 匹配查找器对编码器速度、内存使用量和压缩率有重大影响。 通常,哈希链匹配查找器比二叉树匹配查找器更快。
默认值取决于预设:0 使用 hc3,1–3 使用 hc4,其余使用 bt4。
支持以下匹配查找器。 下面是内存使用公式,它们都是近似值,并且在 dict 是 2 的幂时最接近实际值。
hc3 使用 2 字节和 3 字节哈希的哈希链
好的值的最小值为:3 内存使用量: dict * 7.5(如果 dict <= 16 MiB); dict * 5.5 + 64 MiB(如果 dict > 16 MiB)
hc4 使用 2 字节、3 字节和 4 字节哈希的哈希链
好的值的最小值为:4 内存使用量: dict * 7.5(如果 dict <= 32 MiB); dict * 6.5(如果 dict > 32 MiB)
bt2 使用 2 字节哈希的二叉树
好的值的最小值为:2 内存使用量:dict * 9.5
bt3 使用 2 字节和 3 字节哈希的二叉树
好的值的最小值为:3 内存使用量: dict * 11.5(如果 dict <= 16 MiB); dict * 9.5 + 64 MiB(如果 dict > 16 MiB)
bt4 使用 2 字节、3 字节和 4 字节哈希的二叉树
好的值的最小值为:4 内存使用量: dict * 11.5(如果 dict <= 32 MiB); dict * 10.5(如果 dict > 32 MiB)
mode=mode
压缩模式指定分析匹配查找器生成的数据时使用的方法。支持的模式为 fast 和 normal。默认情况下,对于预设 0-3,默认值为 fast;对于预设 4-9,默认值为 normal。
通常,fast 与哈希链匹配查找器一起使用,normal 与二叉树匹配查找器一起使用。预设也是如此。
nice=nice
指定被认为是“好”匹配的长度。一旦找到至少达到 nice 字节的匹配,算法就会停止寻找可能更好的匹配。
Nice 的范围为 2-273 字节。较高的值往往可以提供更好的压缩比,但会降低速度。默认值取决于预设。
depth=depth
指定匹配查找器中的最大搜索深度。默认值为特殊值 0,这使得压缩器可以从 mf 和 nice 中确定一个合理的深度。
哈希链的合理深度为 4-100,二叉树的合理深度为 16-1000。使用非常高的深度值可能会导致编码器对某些文件而言速度极慢。除非您准备好在压缩需要花费过多时间时中断压缩,否则请避免将深度设置超过 1000。
在解码原始流(--format=raw)时,LZMA2 只需要字典大小。LZMA1 还需要 lc、lp 和 pb。
--x86[=options]
--arm[=options]
--armthumb[=options]
--arm64[=options]
--powerpc[=options]
--ia64[=options]
--sparc[=options]
--riscv[=options]
在过滤器链中添加分支/调用/跳转 (BCJ) 过滤器。这些过滤器只能用作过滤器链中的非最后一个过滤器。
BCJ 过滤器将机器代码中的相对地址转换为其绝对对应地址。这不会改变数据的大小,但会增加冗余,这可以帮助 LZMA2 生成小 0-15% 的 .xz 文件。BCJ 过滤器始终是可逆的,因此对错误类型的数据使用 BCJ 过滤器不会导致任何数据丢失,尽管它可能会使压缩比略微降低。BCJ 过滤器速度非常快,并且使用的内存量可以忽略不计。
这些 BCJ 过滤器存在已知的与压缩比相关的问题:
某些包含可执行代码的文件(例如,目标文件、静态库和 Linux 内核模块)的指令中的地址填充了填充值。这些 BCJ 过滤器仍然会执行地址转换,这会使这些文件的压缩效果变差。
如果将 BCJ 过滤器应用于存档,则可能会降低压缩比,甚至比不使用 BCJ 过滤器还要差。例如,如果存在相似甚至相同的可执行文件,则过滤可能会使文件变得不那么相似,从而导致压缩效果更差。存档中非可执行文件的内容也可能产生影响。在实践中,必须尝试使用和不使用 BCJ 过滤器,以查看哪种方法更好。
不同的指令集具有不同的对齐方式:可执行文件必须与输入数据对齐到该值的倍数,才能使过滤器正常工作。
过滤器 对齐 说明 x86 1 32 位或 64 位 x86 ARM 4 ARM-Thumb 2 ARM64 4 最好使用 4096 字节对齐 PowerPC 4 仅支持大端 IA-64 16 Itanium SPARC 4 RISC-V 2
由于 BCJ 过滤后的数据通常使用 LZMA2 进行压缩,因此如果将 LZMA2 选项设置为与所选 BCJ 过滤器对齐,则压缩率可能会略有提高。示例:
IA-64 过滤器具有 16 字节对齐,因此 pb=4,lp=4,lc=0 在 LZMA2 中效果良好(2^4=16)。
RISC-V 代码具有 2 字节或 4 字节对齐,具体取决于文件是否包含 16 位压缩指令(C 扩展)。当使用 16 位指令时,pb=2,lp=1,lc=3 或 pb=1,lp=1,lc=3 效果良好。当没有 16 位指令时,pb=2,lp=2,lc=2 是最佳选择。可以使用 readelf -h 检查“Flags”行中是否出现“RVC”。
ARM64 始终为 4 字节对齐,因此 pb=2,lp=2,lc=2 是最佳选择。
x86 过滤器是一个例外。通常,最好坚持使用 LZMA2 的默认设置(pb=2,lp=0,lc=3)来压缩 x86 可执行文件。
所有 BCJ 过滤器都支持相同的选项:
start=偏移量
指定在相对地址和绝对地址之间进行转换时使用的起始偏移量。偏移量必须是过滤器对齐值的倍数(请参见上表)。默认值为零。实际上,默认值很好;指定自定义偏移量几乎没有用处。
--delta[=选项]
将 Delta 过滤器添加到过滤器链中。Delta 过滤器只能用作过滤器链中的非最后一个过滤器。
当前仅支持简单的逐字节 Delta 计算。当压缩未压缩的位图图像或未压缩的 PCM 音频时,这可能会很有用。但是,专用算法与 Delta + LZMA2 相比,可能会产生更好的结果。特别是对于音频,使用 flac(1) 等方法可以更快、更好地进行压缩。
支持的选项:
dist=距离
指定 Delta 计算中的距离(以字节为单位)。距离必须为 1–256。默认值为 1。
例如,对于 dist=2 且输入为 A1 B1 A2 B3 A3 B5 A4 B7,输出将为 A1 B1 01 02 01 02 01 02。
其他选项
-q, --quiet
抑制警告和通知。指定两次以抑制错误。此选项不会影响退出状态。也就是说,即使抑制了警告,用于指示警告的退出状态仍然使用。
-v, --verbose
显示详细信息。如果标准错误连接到终端,xz 将显示进度指示器。指定 --verbose 两次将显示更多详细信息。
进度指示器显示以下信息:
如果已知输入文件的大小,则显示完成百分比。也就是说,无法在管道中显示百分比。
压缩或解压缩时生成或消耗的压缩数据量。
压缩时消耗或解压缩时生成的未压缩数据量。
压缩比,它是通过将到目前为止处理的压缩数据量除以到目前为止处理的未压缩数据量来计算的。
压缩或解压缩速度。这被测量为每秒消耗(压缩)或生成(解压缩)的未压缩数据量。在 xz 开始处理文件后几秒钟,会显示此速度。
经过的时间,格式为 M:SS 或 H:MM:SS。
仅当已知输入文件的大小并且自 xz 开始处理文件以来已经过去了几秒钟时,才会显示估计的剩余时间。时间以不太精确的格式显示,该格式从不包含任何冒号,例如,2 分 30 秒。
当标准错误输出不是终端时,--verbose 会使 xz 将文件名、压缩大小、未压缩大小、压缩比以及可能还包括速度和经过时间,在一行中打印到标准错误输出中,以供压缩或解压缩文件使用。仅当操作持续了几秒钟时,才会包括速度和经过时间。如果操作未完成,例如,由于用户中断,如果已知输入文件的大小,则还会打印完成百分比。
-Q, --no-warn
即使检测到值得警告的情况,也不要将退出状态设置为 2。此选项不会影响详细程度,因此必须同时使用 --quiet 和 --no-warn 才能不显示警告,并且不更改退出状态。
--robot
以机器可解析的格式打印消息。这旨在方便编写前端程序,这些程序希望使用 xz 代替 liblzma,这可能是各种脚本的情况。启用此选项后,输出对于 xz 的各个版本应该是稳定的。有关详细信息,请参阅 ROBOT 模式部分。
--info-memory
以人类可读的格式显示物理内存(RAM)和处理器线程的数量,以及 xz 认为系统具有的内存使用限制,以及压缩和解压缩的内存使用限制,然后成功退出。
-h, --help
显示一个帮助消息,其中描述了最常用的选项,然后成功退出。
-H, --long-help
显示一个帮助消息,其中描述了 xz 的所有功能,然后成功退出。
-V, --version
以人类可读的格式显示 xz 和 liblzma 的版本号。要获得机器可解析的输出,请在 --version 之前指定 --robot。
ROBOT 模式
使用 --robot 选项激活机器人模式。这使得 xz 的输出更容易被其他程序解析。目前,--robot 仅与 --list、--filters-help、--info-memory 和 --version 结合使用。将来,它将支持压缩和解压缩。
列表模式
xz --robot --list 使用制表符分隔的输出。每一行的第一列都有一个字符串,指示该行中找到的信息类型:
name 这是开始列出文件时始终的第一行。该行的第二列是文件名。
file 此行包含关于 .xz 文件的总体信息。此行始终在 name 行之后打印。
stream 只有在指定了 --verbose 时,才会使用此行类型。.xz 文件中包含多少个流,就会有多少个流行。
block 只有在指定了 --verbose 时,才会使用此行类型。.xz 文件中包含多少个块,就会有多少个块行。块行在所有流行之后显示;不同类型的行不会交错显示。
summary
此行类型仅在两次指定 --verbose 时使用。此行在所有块行之后打印。与 file 行类似,summary 行包含关于 .xz 文件的总体信息。 totals 此行始终是列表输出的最后一行。它显示了总计数和大小。
文件行的列: ### 文件中流的数量 ### 流中的总块数 ### 文件的压缩大小 ### 文件的解压缩大小 ### 压缩比,例如,0.123。如果比率超过 9.999,则显示三个破折号 (---),而不是比率。 ### 逗号分隔的完整性检查名称列表。以下字符串用于已知的检查类型:None、CRC32、CRC64 和 SHA-256。对于未知的检查类型,使用 Unknown-N,其中 N 是十进制形式的检查 ID(一个或两个数字)。 ### 文件中流填充的总大小
流行的列: ### 流编号(第一个流为 1) ### 流中的块数 ### 压缩起始偏移量 ### 解压缩起始偏移量 ### 压缩大小(不包括流填充) ### 解压缩大小 ### 压缩比 ### 完整性检查的名称 流填充的大小
块行的列: ### 包含此块的流的编号 ### 相对于流开头的块编号(第一个块为 1) ### 相对于文件开头的块编号 ### 相对于文件开头的压缩起始偏移量 ### 相对于文件开头的解压缩起始偏移量 ### 块的总压缩大小(包括标题) ### 解压缩大小 ### 压缩比 完整性检查的名称
如果指定了 --verbose 两次,则块行中将包含额外的列。由于获取此信息需要进行许多查找操作,因此在只指定 --verbose 时,这些列不会显示,因为这样会比较慢: 以十六进制形式显示完整性检查的值 块标题大小 块标志:c 表示存在压缩大小,u 表示存在解压缩大小。如果未设置标志,则显示一个破折号 (-) 以保持字符串长度固定。未来可能会在字符串末尾添加新的标志。 块中实际压缩数据的大小(不包括块标题、块填充和检查字段) 使用此 xz 版本解压缩此块所需的内存量(以字节为单位) 过滤器链。请注意,在压缩时使用的大多数选项都无法知道,因为只有在 .xz 标题中存储了解压缩时需要的选项。
摘要行中的列: ### 解压缩此文件所需的内存量(以字节为单位),使用此 xz 版本 是或否,表示所有块头是否都存储了压缩大小和未压缩大小。 自 xz 5.1.2alpha 起: ### 解压缩此文件所需的最低 xz 版本
总计行中的列: ### 流的数量 ### 块的数量 ### 压缩大小 ### 未压缩大小 ### 平均压缩比 ### 逗号分隔的已存在于文件中的完整性检查名称列表 ### 流填充大小 ### 文件的数量。 此处是为了保持早期列的顺序与文件行中的顺序相同。
如果指定了两次 --verbose,则会在总计行中包含额外的列: 使用此 xz 版本解压缩文件所需的内存的最大量(以字节为单位) 是或否,表示所有块头是否都存储了压缩大小和未压缩大小。 自 xz 5.1.2alpha 起: 解压缩此文件所需的最低 xz 版本
未来的版本可能会添加新的行类型,并且可以向现有行类型添加新的列,但现有的列不会更改。
过滤器帮助
xz --robot --filters-help 以以下格式打印受支持的过滤器:
filter:option=<value>,option=<value>...
filter 过滤器名称
option 过滤器特定选项的名称
value 数字值范围显示为 <min-max>。字符串值选项显示在 < > 中,并用 | 字符分隔。
每个过滤器打印在单独的一行。
### 内存限制信息
xz --robot --info-memory 打印单行,其中包含多个用制表符分隔的列:
### 总物理内存(RAM)量(以字节为单位)。
### 压缩的内存使用限制(以字节为单位)(--memlimit-compress)。特殊值 0 表示默认设置,对于单线程模式,这与没有限制相同。
### 解压缩的内存使用限制(以字节为单位)(--memlimit-decompress)。特殊值 0 表示默认设置,对于单线程模式,这与没有限制相同。
### 自 xz 5.3.4alpha 起:多线程解压缩的内存使用量(以字节为单位)(--memlimit-mt-decompress)。 这永远不会为零,因为如果没有显式指定限制,则使用系统特定的默认值,如列 5 中所示。 这也永远不会大于列 3 中的值,即使使用 --memlimit-mt-decompress 显式指定了更大的值。
自 xz 5.3.4alpha 版本起:一个系统特定的默认内存使用限制,用于限制在自动线程数模式下(--threads=0)压缩时以及未指定内存使用限制(--memlimit-compress)时,线程的数量。它也用作 --memlimit-mt-decompress 的默认值。
自 xz 5.3.4alpha 版本起:可用的处理器线程数。
在未来,xz --robot --info-memory 的输出可能会有更多列,但永远不会超过一行。
版本
xz --robot --version 打印 xz 和 liblzma 的版本号,格式如下:
XZ_VERSION=XYYYZZZS
LIBLZMA_VERSION=XYYYZZZS
X 主版本号。
YYY 次版本号。偶数表示稳定版本,奇数表示 alpha 或 beta 版本。
ZZZ 稳定版本的补丁级别,或者开发版本的计数器。
S 稳定性。0 表示 alpha,1 表示 beta,2 表示稳定。当 YYY 为偶数时,S 应该始终为 2。
如果 xz 和 liblzma 来自同一版本的 XZ Utils,则 XYYYZZZS 在两行中都相同。
示例:4.999.9beta 是 49990091,5.0.0 是 50000002。
退出状态
0 一切正常。
1 发生错误。
2 发生了一些值得警告的事情,但没有实际错误。
打印到标准错误的通知(而不是警告或错误)不会影响退出状态。
环境
xz 首先解析环境变量 XZ_DEFAULTS 和 XZ_OPT 中的空格分隔的选项列表,然后解析命令行中的选项。请注意,只有选项会被解析,所有非选项都会被静默忽略。解析使用 getopt_long(3) 进行,该函数也用于命令行参数。
警告:通过设置这些环境变量,实际上是在修改运行 xz 的程序和脚本。大多数情况下,通过环境变量设置内存使用限制、线程数和压缩选项是安全的。但是,某些选项可能会破坏脚本。一个明显的例子是 --help,它会使 xz 显示帮助文本,而不是压缩或解压缩文件。更微妙的例子是 --quiet 和 --verbose。在许多情况下,使用 --verbose 启用进度指示器可以很好地工作,但在某些情况下,额外的消息会产生问题。详细程度也会影响 --list 的行为。
XZ_DEFAULTS
用户特定的或系统范围内的默认选项。通常,这会在 shell 初始化脚本中设置,以默认启用 xz 的内存使用限制器或设置默认线程数。除了 shell 初始化脚本和其他特殊情况,脚本不应设置或取消设置 XZ_DEFAULTS。
XZ_OPT 用于在无法直接在 xz 命令行上设置选项时,将选项传递给 xz。例如,当 xz 由脚本或工具运行,例如 GNU [tar]({filename}../../tar)(1)。
XZ_OPT=-2v tar caf foo.tar.xz foo
脚本可以使用 XZ_OPT,例如,设置脚本特定的默认压缩选项。 仍然建议允许用户覆盖 XZ_OPT,如果这样做是合理的。 例如,在 sh(1) 脚本中,可以使用如下内容:
XZ_OPT=${XZ_OPT-"-7e"}
export XZ_OPT
LZMA 工具兼容性
xz 的命令行语法实际上是 lzma、unlzma 和 lzcat 的超集,这些工具来自 LZMA Utils 4.32.x。 在大多数情况下,可以用 XZ 工具替换 LZMA 工具,而不会破坏现有的脚本。 然而,存在一些不兼容之处,有时可能会导致问题。
压缩预设级别
xz 和 LZMA 工具中,压缩级别预设的编号并不相同。 最重要的区别在于字典大小如何映射到不同的预设。 字典大小大致等于解压缩器的内存使用量。
级别 xz LZMA 工具 -0 256 KiB N/A -1 1 MiB 64 KiB -2 2 MiB 1 MiB -3 4 MiB 512 KiB -4 4 MiB 1 MiB -5 8 MiB 2 MiB -6 8 MiB 4 MiB -7 16 MiB 8 MiB -8 32 MiB 16 MiB -9 64 MiB 32 MiB
字典大小的差异也会影响压缩器的内存使用量,但 LZMA 工具和 XZ 工具之间还存在一些其他差异,这使得差异更大:
级别 xz LZMA 工具 4.32.x -0 3 MiB N/A -1 9 MiB 2 MiB -2 17 MiB 12 MiB -3 32 MiB 12 MiB -4 48 MiB 16 MiB -5 94 MiB 26 MiB -6 94 MiB 45 MiB -7 186 MiB 83 MiB -8 370 MiB 159 MiB -9 674 MiB 311 MiB
LZMA 工具中的默认预设级别为 -7,而在 XZ 工具中为 -6,因此两者默认使用 8 MiB 字典。
流式与非流式 .lzma 文件
未压缩文件的大小可以存储在 .lzma 标头中。 LZMA 工具在压缩常规文件时会这样做。 另一种方法是标记未压缩大小未知,并使用末尾标记来指示解压缩器应该停止的位置。 LZMA 工具在未压缩大小未知时使用此方法,例如,在管道中。
xz 支持解压缩带有或不带有末尾标记的 .lzma 文件,但由 xz 创建的所有 .lzma 文件都将使用末尾标记,并且 .lzma 标头中将标记未压缩大小未知。 在某些不常见的情况下,这可能会成为一个问题。 例如,嵌入式设备中的 .lzma 解压缩器可能仅适用于具有已知未压缩大小的文件。 如果遇到此问题,则需要使用 LZMA 工具或 LZMA SDK 来创建具有已知未压缩大小的 .lzma 文件。
不支持的 .lzma 文件
.lzma 格式允许 lc 值为最多 8,lp 值为最多 4。 LZMA Utils 可以解压缩具有任意 lc 和 lp 值的压缩文件,但始终创建 lc=3 和 lp=0 的文件。 可以使用 xz 和 LZMA SDK 创建具有其他 lc 和 lp 值的压缩文件。
liblzma 中 LZMA1 过滤器的实现要求 lc 和 lp 的总和不能超过 4。 因此,超过此限制的 .lzma 文件无法使用 xz 解压缩。
LZMA Utils 创建的 .lzma 文件仅具有 2^n(2 的幂)的字典大小,但可以接受具有任意字典大小的文件。 liblzma 仅接受具有 2^n 或 2^n + 2^(n-1) 字典大小的 .lzma 文件。 这是为了减少检测 .lzma 文件时的误报。
这些限制在实践中不应该成为问题,因为实际上所有 .lzma 文件都是使用 liblzma 将能够接受的设置进行压缩的。
尾部垃圾数据
在解压缩时,LZMA Utils 会静默地忽略第一个 .lzma 流之后的所有内容。 在大多数情况下,这是一种错误。 这也意味着 LZMA Utils 不支持解压缩串联的 .lzma 文件。
如果第一个 .lzma 流之后还有数据,xz 认为该文件已损坏,除非使用了 --single-stream 选项。 这可能会破坏一些假定尾部垃圾数据会被忽略的脚本。
注意事项
压缩输出可能会有所不同
即使压缩选项相同,从相同的未压缩输入文件生成的精确压缩输出在不同的 XZ Utils 版本之间也可能不同。 这是因为编码器可以在不影响文件格式的情况下进行改进(速度更快或压缩效果更好)。 即使在同一 XZ Utils 版本的不同构建之间,如果使用了不同的构建选项,输出也可能会有所不同。
这意味着,一旦实现了 --rsyncable 选项,结果文件不一定能够进行 rsync 同步,除非旧文件和新文件都使用相同的 xz 版本进行压缩。 可以通过冻结编码器实现的一部分来保持 rsyncable 输出的稳定性,从而解决此问题。
嵌入式 .xz 解压缩器
像 XZ Embedded 这样的嵌入式 .xz 解压缩器实现不一定支持使用其他完整性检查类型(例如 none 和 crc32)创建的文件。 由于默认值为 --check=crc64,因此在使用时必须使用 --check=none 或 --check=crc32 来为嵌入式系统创建文件。
在嵌入式系统之外,所有 .xz 格式的解压缩器都支持所有检查类型,或者至少能够解压缩文件,而无需验证特定的检查(如果该检查不受支持)。
XZ Embedded 支持 BCJ 过滤器,但仅支持默认的起始偏移量。
示例
基本用法
将文件 foo 压缩为 foo.xz,并使用默认压缩级别 (-6),并在压缩成功后删除 foo:
xz foo
将 bar.xz 解压缩为 bar,并且即使解压缩成功,也不删除 bar.xz:
xz -dk bar.xz
使用预设 -4e(-4 --extreme)创建 baz.tar.xz,该预设比默认的 -6 速度更慢,但压缩和解压缩时需要的内存更少(分别为 48 MiB 和 5 MiB):
tar cf - baz | xz -4e > baz.tar.xz
可以使用单个命令解压缩混合压缩和未压缩的文件到标准输出:
xz -dcf a.txt b.txt.xz c.txt d.txt.lzma > abcd.txt
并行压缩多个文件
在 GNU 和 BSD 上,可以使用 find(1) 和 xargs(1) 来并行压缩多个文件:
find . -type f \! -name '*.xz' -print0 \
| xargs -0r -P4 -n16 xz -T1
xargs(1) 的 -P 选项设置并行 xz 进程的数量。-n 选项的最佳值取决于要压缩的文件的数量。如果只有几个文件,则该值可能应该是 1;如果有数万个文件,则 100 甚至更多可能更合适,以减少 xargs(1) 最终将创建的 xz 进程数量。
xz 的 -T1 选项是为了强制其进入单线程模式,因为 xargs(1) 用于控制并行化的程度。
机器人模式
计算在压缩多个文件后总共节省了多少字节:
xz --robot --list *.xz | awk '/^totals/{print $5-$4}'
脚本可能需要知道它是否正在使用足够新的 xz。以下 sh(1) 脚本检查 xz 工具的版本号是否至少为 5.0.0。这种方法与旧的 beta 版本兼容,旧版本不支持 --robot 选项:
if ! eval "$(xz --robot --version 2> /dev/null)" ||
[ "$XZ_VERSION" -lt 50000002 ]; then
echo "您的 xz 版本太旧。"
fi
unset XZ_VERSION LIBLZMA_VERSION
使用 XZ_OPT 设置解压缩的内存使用限制,但如果已经设置了限制,则不要增加它:
NEWLIM=$((123 << 20)) # 123 MiB
OLDLIM=$(xz --robot --info-memory | cut -f3)
if [ $OLDLIM -eq 0 -o $OLDLIM -gt $NEWLIM ]; then
XZ_OPT="$XZ_OPT --memlimit-decompress=$NEWLIM"
export XZ_OPT
fi
自定义压缩器过滤器链
自定义过滤器链的最简单用法是自定义 LZMA2 预设。这可能很有用,因为预设只涵盖了潜在有用组合的子集。
选项 -0 ... -9 和 --extreme 描述中的 CompCPU 列在自定义 LZMA2 预设时很有用。以下是从这两个表中收集的相关部分:
预设 CompCPU -0 0 -1 1 -2 2 -3 3 -4 4 -5 5 -6 6 -5e 7 -6e 8
如果您知道某个文件需要较大的字典(例如 32 MiB)才能很好地压缩,但您希望以比 xz -8 更快的方式压缩它,则可以使用较低的 CompCPU 值(例如 1)的预设,并将其修改为使用更大的字典:
xz --lzma2=preset=1,dict=32MiB foo.tar
对于某些文件,上述命令可能比 xz -6 更快,同时压缩率也更高。 但是,必须强调的是,只有某些文件才能从大型字典中受益,同时保持较低的 CompCPU 值。 最明显的情况是,大型字典可以提供很大的帮助,即包含许多相似文件的存档,每个文件至少有几兆字节。 字典大小必须明显大于任何单个文件,以便 LZMA2 能够充分利用连续文件之间的相似之处。
如果可以接受非常高的压缩器和解压缩器内存使用量,并且要压缩的文件至少有几百兆字节,则可以使用比 xz -9 使用的 64 MiB 更大的字典:
xz -vv --lzma2=dict=192MiB big_foo.tar
在上面的示例中使用 -vv(--verbose --verbose)可以帮助查看压缩器和解压缩器的内存需求。 请记住,使用大于未压缩文件大小的字典会浪费内存,因此上述命令对小型文件没有用处。
有时,压缩时间并不重要,但必须将解压缩器的内存使用量保持在较低水平,例如,以便能够在嵌入式系统上解压缩该文件。 以下命令使用 -6e(-6 --extreme)作为基础,并将字典设置为仅 64 KiB。 结果文件可以使用 XZ Embedded(这就是为什么使用 --check=crc32)解压缩,使用大约 100KiB 的内存。
xz --check=crc32 --lzma2=preset=6e,dict=64KiB foo
如果您想尽可能地压缩更多的字节,那么调整字面上下文位数(lc)和位置位数(pb)有时会有所帮助。 调整字面位置位数(lp)可能也有帮助,但通常 lc 和 pb 更重要。 例如,源代码存档主要包含 US-ASCII 文本,因此以下内容可能比 xz -6e 产生略小的文件(也请尝试不使用 lc=4):
xz --lzma2=preset=6e,pb=0,lc=4 source_code.tar
使用另一个过滤器与 LZMA2 结合使用可以改善某些文件类型的压缩效果。 例如,要使用 x86 BCJ 过滤器压缩 x86-32 或 x86-64 共享库:
xz --x86 --lzma2 libfoo.so
请注意,过滤器选项的顺序非常重要。 如果在 --lzma2 之后指定 --x86,xz 将会报错,因为不能在 LZMA2 之后使用任何过滤器,并且 x86 BCJ 过滤器不能用作链中的最后一个过滤器。
Delta 过滤器与 LZMA2 结合使用可以为位图图像提供良好的结果。 通常,它应该优于 PNG,PNG 具有一些比简单的 delta 过滤器更高级的过滤器,但使用 Deflate 进行实际压缩。
图像必须以未压缩格式保存,例如,作为未压缩的 TIFF。 Delta 过滤器的距离参数设置为与图像中每个像素的字节数相匹配。 例如,24 位 RGB 位图需要 dist=3,并且最好将 pb=0 传递给 LZMA2,以适应三字节对齐:
xz --delta=dist=3 --lzma2=pb=0 foo.tiff
如果多个图像被放入单个存档中(例如,.tar),Delta 过滤器也可以处理,只要所有图像具有相同数量的像素/字节。
参阅
xzdec(1), xzdiff(1), xzgrep(1), xzless(1), xzmore(1), gzip(1), bzip2(1), 7z(1)
XZ 工具:[https://tukaani.org/xz/]
XZ 嵌入式:[https://tukaani.org/xz/embedded.html]
LZMA SDK:[https://7-zip.org/sdk.html]