压缩技能,是 Linux 工程师的必修课,它对提升数据传输效率、降低传输带宽、管理备份数据都有着重要的作用。
而在众多的压缩工具中,gzip 算是在开源界里最常用的一款了。下面,我们就来学习 gzip 压缩和解压大法!
gzip 的身世其实并不是谜,而是众人皆知的。
在很久以前,UNIX 操作系统上的压缩工具叫作 compress,这个压缩工具采用了很著名的 LZW 压缩算法。但是由于 Unisys 和 IBM 拥有 LZW 压缩算法的专利,所以 UNIX 操作系统不能再随意使用这个算法和这个压缩工具了。为了解决这个问题,Jean-loup Gailly 编写了 gzip 压缩工具,完全替代了有专利争议的 compress 工具,从此 gzip 诞生了。
gzip 工具还被囊括进了 GNU 项目中,成为了其中的一员。
gzip 只能针对普通文件(regular file)进行压缩和解压,对于文件夹、符号链接等是不支持的。如果你想把多个文件一起压缩并打包,gzip 自身也是办不到的,需要有它的好兄弟 tar 命令来帮助完成。
下面来演示一下 gzip 单独工作的场景:
#我有一个小视频 [roc@roclinux ruanjian]$ ls -l hero.avi -rw-rw-r-- 1 roc roc 10627631 2月 19 10:37 hero.avi #用gzip开始压缩, 命令就是这么简单 [roc@roclinux ruanjian]$ gzip hero.avi #压缩后, 原文件消失, 出现一个以.gz后缀的新文件, 大小变小了(虽然不多) #如果压缩的是文本文件, 效果会很明显 [roc@roclinux ruanjian]$ ls -l hero.avi.gz -rw-rw-r-- 1 roc roc 10605586 2月 19 10:37 hero.avi.gz #我们再解压回来, 只需加-d选项即可 [roc@roclinux ruanjian]$ gzip -d hero.avi.gz #完璧归赵啦 [roc@roclinux ruanjian]$ ls -l hero.avi -rw-rw-r-- 1 roc roc 10627631 2月 19 10:37 hero.avi #如果想在压缩后, 保留原文件, 那么可以用-c选项实现 #-c选项就是让gzip把压缩的内容输出到标准输出, 而非写入到文件中 [roc@roclinux ruanjian]$ gzip -c hero.avi > hero.avi.gz
虽然 gzip 可以单独工作,但其实平时大家并不总是这么用,最常用的方式还是结合 tar 命令一起来用。我们继续往下看。
虽然 gzip 常用,但 gzip 性格有些低调,通常是隐藏在 tar 打包工具的背后,为用户默默地提供着压缩服务。
这是因为在实际生产环境中,我们遇到的情况通常不是只针对一个文件进行压缩,而是针对多个文件和文件夹一起打包并压缩。而 tar 就是用来打包用的,所以它自然而然就成了各个压缩工具的代言人了。
有些同学可能会问,“打包/拆包”“压缩/解压缩”有什么区别?我们用一个生活中的例子来解释,相信大家会豁然开朗:
在日常的工作中,拆包解压,绝对要比压缩打包的次数多得多。比如我们下载了一个开源软件之后:
#这是我们下载的开源软件包, 大小是3.4MB [roc@roclinux ruanjian]$ ls -hl curl-7.34.0.tar.gz -rw-rw-r-- 1 roc roc 3.4M 2月 17 22:52 curl-7.34.0.tar.gz #我们解压并拆包, 使用了tar -xzvf这样的命令用法 #下面输出的以curl-7.34.0/开头的好多行, 都是拆包和解压的过程 [roc@roclinux ruanjian]$ tar -xzvf curl-7.34.0.tar.gz curl-7.34.0/ curl-7.34.0/depcomp curl-7.34.0/mkinstalldirs curl-7.34.0/docs/ curl-7.34.0/docs/VERSIONS curl-7.34.0/docs/MAIL-ETIQUETTE curl-7.34.0/docs/BINDINGS curl-7.34.0/docs/LIBCURL-STRUCTS curl-7.34.0/docs/BUGS curl-7.34.0/docs/libcurl/ curl-7.34.0/docs/libcurl/curl_share_init.3 curl-7.34.0/docs/libcurl/libcurl.3 curl-7.34.0/docs/libcurl/curl_share_strerror.3 curl-7.34.0/docs/libcurl/curl_free.pdf curl-7.34.0/docs/libcurl/curl_easy_send.html curl-7.34.0/docs/libcurl/curl_easy_reset.3 (此处省略数百行) #解压后, 我们来对比一下解压前后的大小变化。前面说过, 对于文本或代码类的文件, 压缩的效果会非常明显。 [roc@roclinux ruanjian]$ du -sh curl-7.34.0 curl-7.34.0.tar.gz 20M curl-7.34.0 3.4M curl-7.34.0.tar.gz #进入到解压后的文件夹中 [roc@roclinux ruanjian]$ cd curl-7.34.0/ #这就是拆包解压后的内容啦 [roc@roclinux curl-7.34.0]$ ls -F acinclude.m4 CMakeLists.txt configure.ac include/ m4/ maketgz* RELEASE-NOTES aclocal.m4 compile* COPYING install-sh* MacOSX-Framework* missing* src/ buildconf* config.guess* curl-config.in lib/ Makefile mkinstalldirs* tests/ CHANGES config.sub* depcomp* libcurl.pc.in Makefile.am packages/ vs/ CMake/ configure* docs/ ltmain.sh Makefile.in README winbuild/
下面我们回过头来详细介绍一下上面这段例子中的知识点。
首先,在 Linux 的世界里,当我们看到文件后缀是 .tar.gz 或者 .tgz 时,心里应该默念“这是用 gzip 压缩的打包文件”。对于这类文件,我们是可以通过 gzip 来解压的。本例中的 curl-7.34.0.tar.gz 就属于这类。
其次,解压时我们用到了 tar-xzvf 这样复杂晦涩的选项组合,下面来逐一解读一下:
如果你是第一次看到 -xzvf 选项组合,可能会觉得晦涩难记,没关系,多用几次就熟了。我现在手指早已形成了肌肉记忆了。(不知道是该笑还是该哭……)
我们已经练就了“解压大法”,接下来,就要学习怎么创建解压文件了。如果你掌握了刚才所讲的内容,那么创建压缩文件也并非难事。
[roc@roclinux ruanjian]$ tar -czvf mygzipfile.tar.gz curl-7.34.0 curl-7.34.0/ curl-7.34.0/winbuild/ curl-7.34.0/winbuild/gen_resp_file.bat curl-7.34.0/winbuild/MakefileBuild.vc curl-7.34.0/winbuild/Makefile.msvc.names curl-7.34.0/winbuild/BUILD.WINDOWS.txt curl-7.34.0/winbuild/Makefile.vc curl-7.34.0/config.guess curl-7.34.0/Makefile.in curl-7.34.0/CHANGES curl-7.34.0/ltmain.sh (此处省略数百行) #看!我们的tar.gz文件已经新鲜出炉了 [roc@roclinux ruanjian]$ ls -l mygzipfile.tar.gz -rw-rw-r-- 1 roc roc 3567446 2月 19 15:45 mygzipfile.tar.gz
细心观察的话,你会发现打包压缩所用的命令是 tar-czvf,和拆包解压的 -xzvf 非常相似,只是 x 替换成了 c 而已。
有些时候,我们不确定“葫芦里装的什么药”,所以不想直接解压,只想看看里面包括了哪些文件。这时,我们用 tar 命令就可以做到:
[roc@roclinux ruanjian]$ tar -ztvf curl-7.34.0.tar.gz drwxr-xr-x 1000/1000 0 2013-12-17 15:51 curl-7.34.0/ -rwxr-xr-x 1000/1000 23566 2013-11-11 15:47 curl-7.34.0/depcomp -rwxr-xr-x 1000/1000 3538 2013-09-09 06:11 curl-7.34.0/mkinstalldirs drwxr-xr-x 1000/1000 0 2013-12-17 15:51 curl-7.34.0/docs/ -rw-r--r-- 1000/1000 114456 2013-12-17 06:02 curl-7.34.0/lib/http.c (此处省略数百行)
我们使用了 -ztvf 选项实现了“只想看看”的效果,其中少了 -x 选项,却多了 -t 选项:
通过查看 tar.gz 文件中的内容,我们知道了 curl 软件包中有一个 http.c 文件。现在我想提取出 curl-7.34.0/lib/http.c 这个文件,看看它的源码,但是又不想把这个软件压缩包全部解压,该怎么做呢?即我们如何从一个打包压缩的 tar.gz 文件中提取出某一个单独的文件呢?方法总比问题多,揭晓答案:
#原来就在拆包解压命令的后面直接加上要提取的文件全路径就好了, 简单! [roc@roclinux ruanjian]$ tar -xzvf curl-7.34.0.tar.gz curl-7.34.0/lib/http.c curl-7.34.0/lib/http.c #看, 这就是我们单独提取出来的文件 [roc@roclinux ruanjian]$ tree curl-7.34.0 curl-7.34.0 `-- lib `-- http.c 1 directory, 1 file
有些人追求压缩的速度,希望快点完成压缩;而有些人却更追求压缩的强度,希望把东西压缩得越小越好。
gzip 命令确实为用户提供了这样的选择权,包含了九个压缩级别,分别是 1、2、3、4、5、6、7、8、9:
我们来实战一下。
#这是我们的压缩对象, 一个足有1.7GB大小的日志文件, 它是一个实实在在的纯文本文件 [roc@roclinux ruanjian]$ ls -hl error.log -rw-r--r-- 1 roc roc 1.7G 2月 20 14:39 error.log #我们先用“最快速”的压缩等级(1级), 同时使用time来精准计时 [roc@roclinux ruanjian]$ time gzip -1 error.log real 0m22.322s user 0m20.983s sys 0m1.250s #“最快速”压缩等级, 耗时是22.3秒, 压缩后的大小为99MB [roc@roclinux ruanjian]$ ls -hl error.log.gz -rw-r--r-- 1 roc roc 99M 2月 20 14:39 error.log.gz #然后我们再尝试“最强”压缩等级(9级), 同样也使用time来精准计时 [roc@roclinux ruanjian]$ time gzip -9 error.log real 1m3.544s user 1m2.189s sys 0m1.256s #“最强”压缩等级, 耗时变长了许多, 为1分3秒, 但压缩后的文件却是更小了, 为70MB [roc@roclinux ruanjian]$ ls -hl error.log.gz -rw-r--r-- 1 roc roc 70M 2月 20 14:39 error.log.gz
等级数字不好记的话,可以这样记:1 表示一步到位,往往一步到位的东西追求的是快,而不是精致程度。
好了,gzip 命令就讲到这里啦,内容较多,足够大家消化一两天了。