---
title: "为什么 .tar.gz 要两个后缀"
description: "前两天我在重新编译一版 nginx。流程基本闭着眼睛都能走。"
date: 2026-04-13T23:00:00Z
canonical: https://xiaobox.github.io/p/2026-04-13-wei-shen-me-tar-gz-yao-liang-ge-hou-zhui/
author: 小盒子
categories: ["系统底层"]
tags: ["Linux"]
source: https://mp.weixin.qq.com/s/AR1DsJNwUX28Kw_NLKmcmw
license: CC BY-NC-SA 4.0
license_url: https://creativecommons.org/licenses/by-nc-sa/4.0/
---

# 为什么 .tar.gz 要两个后缀

前两天我在重新编译一版 nginx。

流程基本闭着眼睛都能走。`wget` 拉下来一个 `nginx-1.27.4.tar.gz`，`tar -xzvf` 解开，进目录，`./configure`，`make`，`make install`。

敲完 tar 那条命令的一瞬间，我突然愣了一下。

这个 `.tar.gz`，两个后缀。

我用了大概十几年，从来没认真想过为什么要两个。

顺着这事我又想起来，我这双手对 tar 的记忆完全是肌肉记忆，`xzvf` 这四个字母该按什么顺序，大脑是不参与的，手指自己会动。正因为是肌肉记忆，我还踩过一个经典坑，偶尔下载到没有顶层目录的 tar 包，照样一梭子解下去，几十个文件啪一下全炸到当前目录，瞬间把工作目录变成垃圾场。

那种时候我一边 `ls | xargs rm` 一边告诉自己下次一定先 `mkdir`。

但下次还是不会。

**人对每天都在用的东西是最没好奇心的。**

说回 `.tar.gz`。这两个后缀到底是什么关系，为什么非得拆成两个。

我带着这个疑问查了一圈，发现这事比我想象的有趣得多。它不是什么历史包袱，也不是约定俗成的命名习惯，它是两个时代两个工具掰着手指头拼出来的一个结果。

先说 tar。

tar 这个命令，最早出现在 1979 年 1 月的 Unix Version 7 里，AT&T 贝尔实验室做的。名字也没什么加密的缩写，就是 Tape ARchive。翻译过来，磁带归档。字面意思。

你可以想象一下 1979 年。那会儿大家备份数据靠的是磁带，就是老电影里那种两个圆盘转啊转的大盘子，数据一圈一圈顺序刻在带子上。你不能跳着读，也不能中间插一段，只能从头到尾一次性过。

![Image](https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2026-04-13-wei-shen-me-tar-gz-yao-liang-ge-hou-zhui/001-c4cd4c83.png)

tar 这个工具的出生使命，就是为了给磁带服务的。

所以它做的事情特别简单，就一个动作，把一堆小文件按顺序拼成一条长长的字节流，好让磁带机一口气写下去。

注意，我说的是「拼成一条流」。

**tar 压根就不压缩。**

你拿 tar 把一个 100MB 的目录打成一个包，出来的文件还是 100MB，一个字节都没省。它只是把这些东西排成一列而已，没做别的事情。

tar 文件内部的最小单位是 512 字节一块，这个数字也不是随便选的。它就是 Unix V7 文件系统磁盘扇区的大小。1979 年的一个选择，刻在所有 tar 文件的基因里，一直刻到今天。 所以 tar 管的事情，就到「拼」为止。

那压缩呢？

tar 不管。

这事儿一直到 1992 年才有人接手。

那一年，两个叫 Jean-loup Gailly 和 Mark Adler 的人做了一个东西叫 gzip。Gailly 写压缩，Adler 写解压，1992 年 10 月 31 号，gzip 0.1 正式发布。

这里有个背景值得一提。在 gzip 之前，Unix 自带的压缩工具叫 compress，用的是 LZW 算法。但 LZW 被 Unisys 和 IBM 捏在手里，九十年代初开始到处收钱，开源圈被整得很紧张。gzip 就是被逼出来的替代品，用的是另一个叫 DEFLATE 的算法，完美绕开了专利地雷。

这段往事本身就够写一篇文章的，但今天我们只关心一个点。

gzip 做的事也特别简单，就一个动作，把一条字节流压缩成一条更短的字节流。

你注意到了吗？gzip 也很轴。它只认「一条流」。你不能拿 gzip 去压一个目录，它不认识目录这回事。给它一个文件，它就吐一个压缩后的文件，给它一条流，它就吐一条压缩后的流。别的事它一概不管。

tar 只打包不压缩，gzip 只压缩不打包。

两个工具，谁都不会干对方的活。

那怎么办？

中间用一根 Unix 管道粘起来。

```
tar cf - mydir | gzip > mydir.tar.gz

```

![Image](https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2026-04-13-wei-shen-me-tar-gz-yao-liang-ge-hou-zhui/002-1c3931bc.png)

这条命令左边 tar 把 `mydir` 打成一条流，用 `-` 表示「别写文件，直接吐到标准输出」。中间一个 `|`，把这条流接到 gzip 的嘴边。右边 gzip 啃完这条流，吐出一条压缩过的流，重定向到 `mydir.tar.gz`。

一个 `|` 符号，两个工具，一条流水线。

你看到的那个 `.tar.gz`，就是这条流水线走完之后自然掉下来的结果。它的后缀之所以是两个，是因为这个文件真的经历了两道工序。第一道叫 tar，第二道叫 gz。后缀诚实地告诉你它是谁。

这里顺便说一句 tar 后来的 `-z` 参数。

GNU tar 的作者们觉得每次写管道太烦，加了一个 `z` 参数，告诉 tar，你要压缩的时候帮我顺手调一下 gzip。这就是为什么我们今天敲 `tar -xzvf` 这个 `z`。但你要知道，**是 tar 在「替你调 gzip」，不是 tar 自己会压缩。四十五年过去了，tar 本体始终没长出压缩这项能力。**

这个决定非常 Unix，非常硬核。

有意思的是，几乎就在 tar 过着自己小日子的同一年代，大洋对岸的 DOS/Windows 世界走了完全不同的一条路。

1989 年，美国程序员 Phil Katz 在 DOS 上搞出 PKZIP，顺手发明了 `.zip` 格式。zip 跟 tar + gzip 的哲学几乎是正相反的，一个工具同时做两件事，既打包又压缩，一把梭到底。

四年之后的 1993 年，另一个年轻人进场了。俄罗斯程序员 Eugene Roshal 发布命令行 RAR，1995 年又推出图形界面版 WinRAR。RAR 是 Roshal Archive 的缩写，字面意思就是「Roshal 的归档」，一个用作者自己名字命名的格式，主打比 zip 更高的压缩率。

WinRAR 这个软件顺便还成了互联网历史上最著名的「永恒试用版」。它写着 40 天试用期，但过期后不会拦你，只会弹一个很客气的提示让你买 license，你关掉它接着用，下次再弹。这个 40 天续命了二十多年，全球无数人用了一辈子没付过钱，它也不生气。这事本身已经成了一个互联网梗。

![Image](https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2026-04-13-wei-shen-me-tar-gz-yao-liang-ge-hou-zhui/003-12bd445d.png)

这一路跟 Unix 那边的区别非常明显，一个软件管到底，打包压缩全包在一个 exe 里。后来 1999 年俄罗斯人 Igor Pavlov 又搞了开源的 7-Zip，自带一个 `.7z` 格式，压缩率再往上提一截。1996 年 Julian Seward 做的 bzip2、2009 年 Lasse Collin 做的 xz 也都先后加入了这个江湖，压缩格式的主要玩家基本就是这些人了。

但你注意到一个很好玩的分化没有。

bzip2 和 xz 这两个后来的家伙，在 Unix 世界里叫什么？`.tar.bz2` 和 `.tar.xz`。tar 先把文件拼成流，bzip2 或者 xz 接着压。**换压缩工具可以，换哲学不行。Unix 那边认死一件事，打包和压缩必须是两件事，永远是两件事。**

Windows 那边正相反，出了更强的算法，就把旧软件整个换掉，一个 exe 管到底。

这已经不只是格式之争了，是两个世界对「一个工具应该长成什么样」的根本分歧。

为什么 Unix 那边坚持要拆？

这就得搬出 Doug McIlroy 了。

1978 年，贝尔实验室的 McIlroy 在 Bell System Technical Journal 上写了一段后来被反复引用的话，核心就三句。

> “
> 
> 写程序要让它们只做一件事，并且把这件事做好。
> 
> 写程序要让它们互相协作。
> 
> 处理的东西最好是文本流，因为那是通用接口。

这就是后来被叫作 Unix 哲学的那一段。

但这段话最有意思的一点，不在文字本身。在于说这话的人是谁。

Doug McIlroy 不光是写这段话的人，他同时还是 Unix 管道 `|` 这个符号的发明者。

![Image](https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2026-04-13-wei-shen-me-tar-gz-yao-liang-ge-hou-zhui/004-470ec597.png)

你品一下这个巧合。

他说「让程序互相协作」的时候，他心里想的不是什么抽象的合作，他想的就是管道。一个程序的输出，通过一根 `|`，无缝流进下一个程序的嘴里。小工具、单一职责、用管道粘起来，组合出任意复杂的流水线。

`.tar.gz` 就是这段话最直白的产物。

tar 是第一个只做一件事的小工具，gzip 是第二个只做一件事的小工具，中间那根 `|` 是 McIlroy 本人发明的管道。你每打一个 `.tar.gz` 文件，都是在重演一遍 1978 年那段话。

这就是为什么我说它是活化石。

化石这个词听起来像是死掉的东西，但 `.tar.gz` 不是。你今天去 GitHub 上随便点一个 C 项目的 release，下载下来的几乎永远是 `.tar.gz`，不是 `.zip`。Linux 内核、nginx、curl、redis，全都是。它不是因为惯性才活着，它是因为那套哲学在今天依然被认为是对的才活着。

所以回到开头那个问题。

为什么 `.tar.gz` 要两个后缀？

因为它不是一个文件，是两个工具排成的一条流水线，每个后缀对应一个工位。你看到的是这条流水线吐出来的结果。

下次你再敲 `tar -xzvf some-thing.tar.gz` 的时候，可以稍微多看两眼那个 `z`。

那个 `z` 不是 tar 在解压。

那是 tar 在回头喊一声 gzip，过来搭把手。

两个工具，一根管道，四十五年。

![Image](https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2026-04-13-wei-shen-me-tar-gz-yao-liang-ge-hou-zhui/005-6c5fb0a0.png)

