gzip命令_Linux gzip命令:壓縮和解壓檔案(.gz檔案)

2020-07-16 10:04:31
壓縮技能,是 Linux 工程師的必修課,它對提升資料傳輸效率、降低傳輸頻寬、管理備份資料都有著重要的作用。

而在眾多的壓縮工具中,gzip 算是在開源界裡最常用的一款了。下面,我們就來學習 gzip 壓縮和解壓大法!

gzip 的身世之謎

gzip 的身世其實並不是謎,而是眾人皆知的。

在很久以前,UNIX 作業系統上的壓縮工具叫作 compress,這個壓縮工具採用了很著名的 LZW 壓縮演算法。但是由於 Unisys 和 IBM 擁有 LZW 壓縮演算法的專利,所以 UNIX 作業系統不能再隨意使用這個演算法和這個壓縮工具了。為了解決這個問題,Jean-loup Gailly 編寫了 gzip 壓縮工具,完全替代了有專利爭議的 compress 工具,從此 gzip 誕生了。

gzip 工具還被囊括進了 GNU 專案中,成為了其中的一員。

gzip 初體驗

gzip 只能針對普通檔案(regular file)進行壓縮和解壓,對於資料夾、符號連結等是不支援的。如果你想把多個檔案一起壓縮並打包,gzip 自身也是辦不到的,需要有它的好兄弟 tar 命令來幫助完成。

下面來演示一下 gzip 單獨工作的場景:
#我有一個小視訊
[[email protected] ruanjian]$ ls -l hero.avi
-rw-rw-r-- 1 roc roc 10627631 2月  19 10:37 hero.avi
 
#用gzip開始壓縮, 命令就是這麼簡單
[[email protected] ruanjian]$ gzip hero.avi
 
#壓縮後, 原檔案消失, 出現一個以.gz字尾的新檔案, 大小變小了(雖然不多)
#如果壓縮的是文字檔案, 效果會很明顯
[[email protected] ruanjian]$ ls -l hero.avi.gz
-rw-rw-r-- 1 roc roc 10605586 2月  19 10:37 hero.avi.gz
 
#我們再解壓回來, 只需加-d選項即可
[[email protected] ruanjian]$ gzip -d hero.avi.gz
 
#完璧歸趙啦
[[email protected] ruanjian]$ ls -l hero.avi
-rw-rw-r-- 1 roc roc 10627631 2月  19 10:37 hero.avi
 
#如果想在壓縮後, 保留原檔案, 那麼可以用-c選項實現
#-c選項就是讓gzip把壓縮的內容輸出到標準輸出, 而非寫入到檔案中
[[email protected] ruanjian]$ gzip -c hero.avi > hero.avi.gz

雖然 gzip 可以單獨工作,但其實平時大家並不總是這麼用,最常用的方式還是結合 tar 命令一起來用。我們繼續往下看。

gzip 的代言人是 tar

雖然 gzip 常用,但 gzip 性格有些低調,通常是隱藏在 tar 打包工具的背後,為使用者默默地提供著壓縮服務。

這是因為在實際生產環境中,我們遇到的情況通常不是只針對一個檔案進行壓縮,而是針對多個檔案和資料夾一起打包並壓縮。而 tar 就是用來打包用的,所以它自然而然就成了各個壓縮工具的代言人了。

有些同學可能會問,“打包/拆包”“壓縮/解壓縮”有什麼區別?我們用一個生活中的例子來解釋,相信大家會豁然開朗:
  • 就像搬家時,我們把每一床棉被都抽成真空,這叫作壓縮,然後把好幾床抽真空的棉被用繩子綑綁起來,這就叫打包。
  • 東西搬到新家後,把繩子解開,就是拆包,然後把每床棉被舒展開,讓棉被鬆軟起來,這就是解壓縮。
  • 如果不抽真空,只是把幾床棉被簡單地用繩子捆起來,那麼就單獨用tar就好了。
  • 如果只有一床棉被,打算抽真空,那麼就用gzip就好了。
  • 如果有好多床棉被,既要抽真空,又要捆起來,那麼就要將tar和gzip結合起來使用。

來看看如何拆包解壓

在日常的工作中,拆包解壓,絕對要比壓縮打包的次數多得多。比如我們下載了一個開源軟體之後:
#這是我們下載的開源軟體包, 大小是3.4MB
[[email protected] 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/開頭的好多行, 都是拆包和解壓的過程
[[email protected] 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
(此處省略數百行)
 
#解壓後, 我們來對比一下解壓前後的大小變化。前面說過, 對於文字或程式碼類的檔案, 壓縮的效果會非常明顯。
[[email protected] 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
 
#進入到解壓後的資料夾中
[[email protected] ruanjian]$ cd curl-7.34.0/
 
#這就是拆包解壓後的內容啦
[[email protected] 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 這樣複雜晦澀的選項組合,下面來逐一解讀一下:
  • -x選項:表示要進行拆包動作。
  • -z選項:表示用 gzip 進行壓縮或解壓縮。如果同時使用了 -x 選項,則表示解壓。如果使用了 -c 選項,則表示壓縮。
  • -v選項:表示在拆包過程中直播整個過程,把已拆包的檔案顯示出來。
  • -f選項:表示指定要拆包的檔案(注意,這個選項一定要放在各個選項的最後,也就是要和所指定的檔名挨得最近)。

如果你是第一次看到 -xzvf 選項組合,可能會覺得晦澀難記,沒關係,多用幾次就熟了。我現在手指早已形成了肌肉記憶了。(不知道是該笑還是該哭……)

tar.gz 檔案是怎麼造出來的

我們已經練就了“解壓大法”,接下來,就要學習怎麼建立解壓檔案了。如果你掌握了剛才所講的內容,那麼建立壓縮檔案也並非難事。
[[email protected] 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檔案已經新鮮出爐了
[[email protected] 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 而已。
  • -c選項:表示要進行打包動作。
  • -z選項:表示用 gzip 進行壓縮或解壓縮。如果同時使用了 -x 選項,則表示解壓。如果使用了 -c 選項,則表示壓縮。
  • -v選項:表示在打包過程中直播整個過程,把已打包的檔案顯示出來。
  • -f選項:表示指定要打包的檔案,完全可以指定多個,資料夾和檔案都可以。

不想解壓,只想看看

有些時候,我們不確定“葫蘆裡裝的什麼藥”,所以不想直接解壓,只想看看裡面包括了哪些檔案。這時,我們用 tar 命令就可以做到:
[[email protected] 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 選項:
  • 少了-x選項:因為我們並不想實際拆包,所以一定要去掉 -x 選項。
  • 多了-t選項:-t 選項的作用是列出打包檔案中的內容,正好符合我們的需求。

有針對性地解壓某個檔案

通過檢視 tar.gz 檔案中的內容,我們知道了 curl 軟體包中有一個 http.c 檔案。現在我想提取出 curl-7.34.0/lib/http.c 這個檔案,看看它的原始碼,但是又不想把這個軟體壓縮包全部解壓,該怎麼做呢?即我們如何從一個打包壓縮的 tar.gz 檔案中提取出某一個單獨的檔案呢?方法總比問題多,揭曉答案:
#原來就在拆包解壓命令的後面直接加上要提取的檔案全路徑就好了, 簡單!
[[email protected] ruanjian]$ tar -xzvf curl-7.34.0.tar.gz
curl-7.34.0/lib/http.c
curl-7.34.0/lib/http.c
 
#看, 這就是我們單獨提取出來的檔案
[[email protected] 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 級”表示壓縮速度最快,但強度不高。
  • “9 級”表示壓縮強度最高,但速度較慢。
  • 預設情況下是 6 級。

我們來實戰一下。
#這是我們的壓縮物件, 一個足有1.7GB大小的紀錄檔檔案, 它是一個實實在在的純文字檔案
[[email protected] ruanjian]$ ls -hl error.log
-rw-r--r-- 1 roc roc 1.7G 2月  20 14:39 error.log
 
#我們先用“最快速”的壓縮等級(1級), 同時使用time來精準計時
[[email protected] ruanjian]$ time gzip -1 error.log
 
real    0m22.322s
user    0m20.983s
sys     0m1.250s
 
#“最快速”壓縮等級, 耗時是22.3秒, 壓縮後的大小為99MB
[[email protected] ruanjian]$ ls -hl error.log.gz
-rw-r--r-- 1 roc roc 99M 2月  20 14:39 error.log.gz
 
#然後我們再嘗試“最強”壓縮等級(9級), 同樣也使用time來精準計時
[[email protected] ruanjian]$ time gzip -9 error.log
 
real    1m3.544s
user    1m2.189s
sys     0m1.256s
 
#“最強”壓縮等級, 耗時變長了許多, 為1分3秒, 但壓縮後的檔案卻是更小了, 為70MB
[[email protected] ruanjian]$ ls -hl error.log.gz
-rw-r--r-- 1 roc roc 70M 2月  20 14:39 error.log.gz

等級數位不好記的話,可以這樣記:1 表示一步到位,往往一步到位的東西追求的是快,而不是精緻程度。

好了,gzip 命令就講到這裡啦,內容較多,足夠大家消化一兩天了。