Linux 基礎學習篇 - Mandrake 9

第十一章、檔案的壓縮與打包 - for Mandrake 9

鳥哥的第一本書籍的主要內容,內容稍微與書籍不太一樣了!

最近更新時間: 2003/05/02

鳥哥的第一本書大約是在 2002 年的年底左右出版的,內容幾乎都是 Linux 基礎學習,一點也沒有談到伺服器的部份!這也是後來的雛型! 不過內容錯誤的地方很多,導致在 2003 年的年底推出了『基礎學習篇增訂版』的內容,大致上就是處理掉一些比較有嚴重錯誤的部份。 不過,因為 Linux 的版本變化非常快速,因此,寫完了這些文件之後,鳥哥還是持續在網站上更新文件內容,導致原本書籍內容的資料與網站資料差異太大! 這個問題直到鳥哥在 2008 年左右才發現!糟糕了!舊版的文件資料已經遺失~覺得相當扼腕~

因此,在底下的文件內容與當初的書籍內容雖然大同小異,不過章節的編排卻是有所不同!再花時間去一個一個處理,似乎也不太符合成本效益! 鳥哥僅是想要將自己以前的文件記錄下來而已,同時將過時的 big5 編碼改回 utf8 編碼,再加上可以支援 RWD 的樣式而已啦! 內容已經不多做編排~因此,如果內容文件你看不懂,那也是應該的! ^_^

建議您前往本站查詢最新版本的 Linux distribution 文章來閱讀,比較不會浪費時間。最新文章請前往鳥站首頁查閱囉!

壓縮的用途與技術

您是否有過文件檔案太大,導致無法以一片軟碟將他複製完成的困擾?又,您是否有過,發現一個軟體裡面有好多檔案,這些檔案要將他複製與攜帶都很不方便的問題?還有,您是否有過要備份某些重要資料,偏偏這些資料量太大了,耗掉了你很多的硬碟與磁碟空間呢?這個時候,那個好用的『檔案壓縮』技術可就派的上用場了!因為這些比較大型的檔案透過所謂的檔案壓縮技術之後,可以將他的磁碟使用量降低,可以達到減低檔案容量的效果,此外,有的壓縮程式還可以進行容量限制,使一個大型檔案可以分割成為數個小型檔案,以方便軟碟片攜帶呢!
 
那麼什麼是『檔案壓縮』呢?我們來稍微談一談他的原理好了。目前我們使用的電腦系統中都是使用所謂的 bytes 單位來計量的!不過,事實上,電腦最小的計量單位應該是 bits 才對啊,此外,我們也知道 1 byte = 8 bits 。但是如果今天我們只是記憶一個數字,亦即是 1 這個數字呢?他會如何記錄?假設一個 byte 可以看成底下的模樣:(註:由於 1 byte = 8 bits ,所以每個 byte 當中會有 8 個空格,而每個空格可以是 0, 1 ,這裡僅是做為一個約略的介紹,讀者不必刻意記憶 )
□□□□□□□□
而由於我們記錄數字是 1 ,考慮電腦所謂的二進位喔,如此一來, 1 會在最右邊佔據 1 個 bit ,而其他的 7 個 bits 將會自動的被填上 0 囉!你看看,其實在這樣的例子中,那 7 個 bits 應該是『空的』才對!不過,為了要滿足目前我們的作業系統資料的存取,所以就會將該資料轉為 byte 的型態來記錄了!而一些聰明的電腦工程師就利用一些複雜的計算方式,將這些沒有使用到的空間『丟』出來,以讓檔案佔用的空間變小!這就是壓縮的技術啦!簡單的說,你可以將他想成,其實檔案裡面有相當多的『空間』存在,並不是完全填滿的,而『壓縮』的技術就是將這些『空間』填滿,以讓整個檔案佔用的容量下降!不過,這些『壓縮過的檔案』並無法直接被我們的作業系統所使用的,因此,若要使用這些被壓縮過的檔案資料,則必須將他『還原』回來未壓縮前的模樣,那就是所謂的『解壓縮』囉!而至於壓縮前與壓縮後的檔案所佔用的磁碟空間大小,就可以被稱為是『壓縮比』囉!更多的技術文件或許你可以參考一下 GNU 計畫當中關於壓縮指令 gzip 的說明文件。當然,我 這裡 也保留一份資料,做為未來參考之用呢!
 
這個『壓縮』與『解壓縮』的動作有什麼好處呢?最大的好處就是壓縮過的檔案容量變小了,所以你的硬碟容量無形之中就可以容納更多的資料,此外,在一些網路資料的傳輸中,也會由於資料量的降低,好讓網路頻寬可以用來作更多的工作!而不是老是卡在一些大型的檔案上面呢!目前很多的 WWW 網站也是利用檔案壓縮的技術來進行資料的傳送,好讓網站的可利用率上升喔!( 註:這種技術蠻有趣的!他讓您網站上面『看的到的資料』在經過網路傳輸時,使用的是『壓縮過的資料』,等到這些壓縮過的資料到達你的電腦主機時,再進行解壓縮,由於目前的電腦運算速度相當的快速,因此其實在網頁瀏覽的時候,時間都是花在『資料的傳輸』上面,而不是 CPU 的運算啦!,如此一來,由於壓縮過的資料量降低了,自然傳送的速度就會增快不少! )若您是一位軟體工程師,那麼相信您也會喜歡將你自己的軟體壓縮之後提供大家下載來使用,畢竟沒有人喜歡自己的網站天天都是頻寬滿載的吧?!舉個例子來說, Linux 2.4.19 完整的核心大小約有 200 MB 左右,而由於核心主要多是 ASCII code 的存文字型態檔案,這種檔案的『多餘空間』最多了。而一個提供下載的壓縮過的 2.4.19 核心大約僅有 30MB 左右,差了幾倍呢?您可以自己算一算喔!

Linux 壓縮檔案的附檔名

如果您常常在網路上面捉 Linux 的資料下來玩的話,大概會曉得的是,這些供人下載的檔案通常都是『壓縮』過的!為了什麼?上面已經稍微提過啦!呵呵!壓縮過的檔案具有節省頻寬、節省磁碟空間等等的優點,並且還方便攜帶呢! ^_^ !而,您應該也會知道,這些被壓縮過的檔案,通常其附檔名都是『 *.tar, *.tar.gz, *.tgz, *.gz, *.Z, *.bz2 』等等的,為什麼要訂定這些壓縮檔案附檔名為這樣的模樣呢?這是因為在 Linux 上面壓縮的指令相當的多,並且,這些壓縮指令可能無法針對每種壓縮檔案都可以解的開,畢竟目前的壓縮技術五花八門,每種壓縮計算的方法都不是完全相同的,所以囉,當你捉到某個壓縮檔時,自然就需要知道壓縮他的是那個指令啦,好用來對照著解壓縮啊! ^_^!也就是說,雖然 Linux 檔案的屬性基本上是與檔名沒有絕對關係的,能不能執行與他的檔案屬性有關而已,與檔名的關係很小!但是,為了幫助我們小小的人類腦袋瓜子,所以適當的檔案名稱附檔名還是必要的!因此,目前就有一些常常見到的壓縮檔案的附檔名啦!我們僅列出常見的幾樣在底下,給大家權做參考之用:
  •  *.Z       compress 程式壓縮的檔案;
  •  *.bz2     bzip2 程式壓縮的檔案;
  •  *.gz      gzip 程式壓縮的檔案;
  •  *.tar     tar 程式打包的資料,並沒有壓縮過;
  •  *.tar.gz  tar 程式打包的檔案,其中並且經過 gzip 的壓縮
目前常見的壓縮程式主要就是如同上面提到的附檔名對應的那些指令啦!最早期的要算是 compress 這個傢伙了,而後,後來的 GNU 計畫開發出新一代的壓縮指令 gzip ( GNU zip ) 用來取代 compress 這個老牌的壓縮指令,再來還有 bzip2 這個壓縮比更好的壓縮指令呢!不過,這些指令通常僅能針對一個檔案來壓縮與解壓縮,如此一來,每次壓縮與解壓縮都要一大堆檔案,豈不煩人?,此時,那個所謂的『打包軟體』就顯的很重要啦!在 Unix-Like 當中,有個軟體很好玩,他就是 tar 這支程式!這個 tar 可以將很多檔案『打包』成為一個檔案!甚至是目錄也可以這麼玩。不過,單純的 tar 功能僅是『打包』而已,亦即是將很多檔案集結成為一個檔案,事實上,他並沒有提供壓縮的功能,後來, GNU 計畫中,將整個 tar 與壓縮的功能結合在一起,如此一來提供使用者更方便並且更強大的壓縮與打包功能!
 
底下我們就來談一談這些在 Linux 底下基本的壓縮指令吧!

  • compress:

  • 語法:
    [root @test /root ]# compress [-d] filename 
    參數說明: 
    -d  :解壓縮的參數! 
    範例: 
    先 copy /etc/man.config 到 root 底下,再將他壓縮看看
    [root @test /root]# cp /etc/man.config /root
    [root @test /root]# compress man.config
    [root @test /root]# compress -d man.config.Z 
    [root @test /root]# uncompress man.config.Z
    這是用來壓縮與解壓縮附檔名為 *.Z 的指令!所以看到 *.Z 的檔案時,就應該要知道他是經由 compress 這個程式壓縮的呦!這是最簡單的壓縮指令囉!不過,使用的時候需要特別留意的是,當你以 compress 壓縮之後,如果沒有下達其他的參數,那麼原本的檔案就會被後來的 *.Z 所取代!以上面的案例來說明:原本壓縮的檔案為 man.config ,那麼當壓縮完成之後,將只會剩下 man.config.Z 這個經過壓縮的檔案囉!那麼解壓縮呢?呵呵,則是將 man.config.Z 解壓縮成 man.config !使用上很簡單啦!解壓縮除了可以使用 compress –d 這個參數之外,也可以直接使用 uncompress !意思相同啦!
     

  • gzip, zcat:

  • 語法:
    [root @test /root ]# gzip [-d#] filename <==壓縮與解壓縮
    [root @test /root ]# zcat filename.gz     <==讀取壓縮檔內容
    參數說明: 
    -d  :解壓縮的參數! 
    -#  :壓縮等級, 1 最不好, 9 最好, 6 是預設值! 
    範例: 
    [root @test /root]# gzip man.config      
    會產生 man.config.gz 這個檔案 

    [root @test /root]# zcat man.config.gz
    會讀取出 man.config 的內容

    [root @test /root]# gzip -d man.config.gz 
    [root @test /root]# gunzip man.config.gz
    解壓縮,產生 man.config 這個檔案

    [root @test /root]# gzip -9 man.config     
    以最大壓縮比壓縮 testing 這個檔案!

    gzip 是用來壓縮與解壓縮附檔名為 *.gz 的指令!所以看到 *.gz 的檔案時,就應該要知道他是經由 gzip 這個程式壓縮的呦!另外, gzip 也提供 壓縮比的服務! -1 是最差的壓縮比,但是壓縮速度最快,而 -9 雖然可以達到較佳的壓縮比(經過壓縮之後,檔案比較小一些!),但是卻會損失一些速度!預設是 -6 這個數值! gzip 也是相當常使用的一個壓縮指令呢!至於 zcat 則是用來讀取壓縮檔資料內容的指令!假如我們剛剛壓縮的檔案是一個文字檔,那麼你還記得如何讀取文字檔嗎?!沒錯!就是使用 cat ,那麼讀取壓縮檔呢?呵呵!就是使用 zcat 囉!由於 gzip 這個壓縮指令主要想要用來取代 compress 的,所以 compress 的壓縮檔案也可以使用 gzip 來解開喔!同時, zcat 這個指令可以同時讀取 compress 與 gzip 的壓縮檔呦!
     

  • bzip2, bzcat:

  • 語法:
    [root @test root]# bzip2 [-dz] filename <==壓縮解壓縮指令
    [root @test root]# bzcat filename.bz2   <==讀取壓縮檔內容指令
    參數說明:
    -d  :解壓縮的意思!
    -z  :壓縮的意思!
    範例:
    同樣的,我們以剛剛拷貝過來的 /root/man.config 這個檔案為例
    [root @test root]# bzip2 –z man.config
    [root @test root]# bzcat man.config.bz2
    [root @test root]# bzip2 –d man.config.bz2
    [root @test root]# bunzip2 man.config.bz2
    剛剛的 compress 附檔名自動建立為 .Z ,這裡的 bzip2 則是自動的將附檔名建置為 .bz2 囉!所以當我們使用具有壓縮功能的 bzip2 –z 時,那麼剛剛的 man.config 就會自動的變成了 man.config.bz2 這個檔名囉!好了,那麼如果我想要讀取這個檔案的內容呢?是否一定要解開?當然不需要囉!可以使用簡便的 bzcat 這個指令來讀取內容即可!例如上面的例子中,我們可以使用 bzcat man.config.bz2 來讀取資料而不需要解開!此外,當您要解開一個壓縮檔時,這個檔案的名稱為 .bz, .bz2, .tbz, .tbz2 等等,那麼就可以嘗試使用 bzip2 來解看看啦!當然囉,也可以使用 bunzip2 這個指令來取代 bzip2 –d 囉
     

  • tar:

  • 語法:
    [root @test /root ]# tar [-zxcvfpP] filename 
    [root @test /root ]# tar -N 'yyyy/mm/dd' /path -zcvf target.tar.gz source 
    參數說明: 
    -z  :是否同時具有 gzip 的屬性? 
    -x  :解開一個壓縮檔案的參數指令! 
    -t  :查看 tarfile 裡面的檔案!
    -c  :建立一個壓縮檔案的參數指令 
    -v  :壓縮的過程中顯示檔案! 
    -f  :使用檔名,請留意,在 f 之後要立即接檔名喔!不要再加參數!
       例如使用『 tar -zcvfP tfile sfile』就是錯誤的寫法,要寫成
       『 tar -zcvPf tfile sfile』才對喔!
    -p  :使用原檔案的原來屬性(屬性不會依據使用者而變) 
    -P  :可以使用絕對路徑 
    -N  :比後面接的日期(yyyy/mm/dd)還要新的才會被打包進新建的檔案中! 
    --exclude FILE:在壓縮的過程中,不要將 FILE 打包! 
    範例: 
    [root @test /root]# tar -cvf  directory.tar    directory 
    只將目錄整合打包成一個檔案 

    [root @test /root]# tar -zcvf directory.tar.gz directory 
    除了將目錄打包外,同時以 gzip 壓縮 

    [root @test /root]# tar -zcvf filename.tar.gz  /home/test/* 
    將 /home/test/ 這個目錄下的檔案全部打包並壓縮成為一個 filename.tar.gz 的檔案

    [root @test /root]# tar -xvf  directory.tar 
    解 tar 的封包,請注意,由於沒有 gzip (.tar 而非 .tar.gz) 的作用,所以只要使用 –xvf 即可!不需要加上 z ,否則會顯示有問題!

    [root @test /root]# tar -zxvf directory.tar.gz 
    這個就是有加上 gzip 的壓縮的結果!所以需要加上 –z 呦!

    [root @test /root]# tar –ztvf directory.tar.gz
    這個 t 可以用來查看 tar 裡面的檔案資訊呢!而不需要將他解開!

    [root @test /root]# tar -zcvPf home.tar.gz /home 
    則建立起來的壓縮檔內檔案為絕對路徑 
    請注意,使用這個 P 的參數時,不要將 P 加在 f 後面,因為
    f 之後要立即接檔名才行喔!

    [root @test /root]# tar -N '2002/06/25' -zcvf home.tar.gz /home 
    上面是說 在 /home 這個目錄中,比 2002/06/25 日還要新的檔案才會被打包進入 home.tar.gz 這個檔案中! 

    [root @test /root]# tar -zcvf host.tar.gz / --exclude /mnt --exclude /proc 
    上面是說,將根目錄的所有資料都打包進 host.tar.gz 這個檔案中,但是 /mnt 及 /proc 則不打包! 

    [root @test /root]# tar -cvf - /home | tar -xvf -
    上面的意思是『將 /home 打包之後,直接解壓縮在 /root 底下!』嘿嘿!不需要再建立一次中間檔案!不過,使用上面的語法最好使用『絕對路徑』,比較不會有問題!這個方式適合不想要建立中間檔案時!

    • 這是一個多用途的壓縮指令!剛剛我們提到的 compress 與 gzip 是可以適用在一個檔案的壓縮上面,但是如果是要壓縮一個目錄呢?!這時該如何是好?!呵呵! tar 就派上用場了! tar 可以將整個目錄或者是規定的檔案都整合成一個檔案!例如上面的第三個範例,他可以將 /home/test 底下的檔案全部整合成一個檔案!而第一個範例中,則是將目錄整合成一個檔案!同時, tar 可以配合 gzip (這個 gzip 的功能已經已經附加上 tar 裡面去了),同時整合並壓縮!呵呵!很方便吧!『 tar 用來作備份是很重要的指令! 』而由於 tar 整合過後的檔案我們通常會取名為 *.tar ,而如果還含有 gzip 的壓縮屬性,那麼就取名為 *.tar.gz 囉!取這個檔名只是為了方便我們記憶這個檔案是什麼屬性罷了!並沒有實際的意義在!
     
    • 另外,需要注意的是,在使用的參數方面,有還有幾個有用的參數需要來瞭解一番,亦即是 -p 與 -P 這兩個!如果你曾經在 crontab 裡面下達過一些備份的指令時,那麼常常會收到 root 的信件,就是說,系統會告訴你『我將 / 的 tar 裡頭的內容拿掉了!』也就是說,原本你備份的檔案是 /home/test ,但是由於擔心未來你在解開壓縮的時候,會產生一些困擾,因為在 tar 裡面的檔案如果是具有『絕對路徑』的話,那麼你解開的檔案將會『一定』在該路徑下也就是 /home/test,而不是絕對路徑(這裡請用心的想一想!),這樣子的最大困擾是,萬一有人拿走了你的這個檔案,並且將該檔案在他的系統上面解開!萬一他的系統上面正巧也有 /home/test 這個目錄,哈哈!他的檔案就會『正巧』被覆蓋了!所以囉,在預設的情況中,如果是以『絕對路徑』來建立打包檔案,那麼將會自動的將 / 拿掉!這是為了剛剛說明的『安全』為前提所做的預設值。好了!但是你就是要以絕對路徑來建立打包的檔案!那麼就加入 -P 這個參數吧(請注意!是大寫字元)!這樣就可以啦!那麼 -p 是什麼(小寫字元)?呵呵!那個 -p 是 permission 的意思,也就是『權限』啦!使用 -p 之後,被打包的檔案將不會依據使用者的身份來改變權限喔!
     
    • 這裡還有一個值得注意的參數呦!那就是在備份的情況中很常使用的 -N 的這個參數!你可以參考一下上面的例子就可以知道啦!在這個例子當中,相當重要的就是那個日期啦!在備份的情況當中,我們都希望只要備份較新的檔案就好了,為什麼呢?因為舊的檔案我們已經有備份囉!幹嘛還要再備份一次,浪費時間也浪費系統資源!這個時候此一參數就顯的相當的重要了啊!
     
    • 在上面的例子中,最後一個例子很有趣『tar cvf - /home | tar -xvf - 』!他是直接以管線命令『 pipe 』來進行壓縮、解壓縮的過程!在上面的例子中,我們想要『將 /home 底下的資料直接 copy 到目前所在的路徑,也就是 /root 底下來』,但是又覺得使用 cp -r 有點麻煩,那麼就直接以這個打包的方式來打包,其中,指令裡面的 - 就是表示那個被打包的檔案啦!由於我們不想要讓中間檔案存在,所以就以這一個方式來進行複製的行為啦!
     
    • tar 的功能相當的多,而由於他是經由『打包』之後再處理的一個過程,所以常常我們會聽到 tarball 的檔案,那就是經由 tar 打包再壓縮的檔案啦!此外, tar 也可以用在備份的儲存媒體上面,最常見的就是磁帶機了!假設我的磁帶機代號為 /dev/st0 ,那麼我要將我的 /home 底下的資料都給他備份上去時,就是使用 tar /dev/st0 /home 就可以啦!很不錯吧!
     
      在 Linux 當中, gzip 已經被整合在 tar 裡面了!但是 Sun 或者其他較舊的 Unix 版本中, 當中的 tar 並沒有整合 gzip ,所以如果你需要解壓縮的話,就需要這麼做:
         
        gzip -d testing.tar.gz
        tar -xvf testing.tar
         
      第一個步驟會將檔案解壓縮,第二個步驟才是將資料解出來!與其他壓縮程式不太一樣的是, bzip2, gzip 與 compress 在沒有加入特殊參數的時候,原先的檔案會被取代掉,但是使用 tar 則原來的與後來的檔案都會存在呦!
     

  • cpio:

  • 語法:
    [root @test /root ]# cpio -covB  > [file|device]<==備份
    [root @test /root ]# cpio -icduv < [file|device]<==還原
    參數說明: 
    -o :將資料 copy 輸出到檔案或裝置上 
    -i :將資料自檔案或裝置 copy 出來系統當中 
    -t :查看 cpio 建立的檔案或裝置的內容 
    -c :一種較新的 portable format 方式儲存 
    -v :讓儲存的過程中檔案名稱可以在螢幕上顯示 
    -B :讓預設的 Blocks 可以增加至 5120 bytes ,預設是 512 bytes ! 
       這樣的好處是可以讓大檔案的儲存速度加快(請參考 i-nodes 的觀念) 
    -d :自動建立目錄!由於 cpio 的內容可能不是在同一個目錄內,
         如此的話在反備份的過程會有問題! 這個時候加上 -d 的話,
         就可以自動的將需要的目錄建立起來了! 
    -u :自動的將較新的檔案覆蓋較舊的檔案! 
    範例: 
    [root @test /root]# find / -print | cpio -covB > /dev/st0 
    將搜尋到的檔案存到磁帶機 

    [root @test /root]# cpio -icduv < /dev/st0 
    將磁帶機的資料還原回來! 

    [root @test /root]# cpio -icdvt < /dev/st0 > /tmp/content 
    將磁帶機的內容(檔名而已)轉存到 /tmp/content 

    [root @test /root]# find / -type -f | cpio -o > /tmp/root.cpio 
    [root @test /root]# cpio -i < /tmp/root.cpio 
    上面這個例子可以馬上實作看看!先輸出到 /tmp/root.cpio 這個檔案,然後再給他還原回來!

    這個 cpio 還蠻神奇的呢!他最適用於備份的時候使用的一個指令了!為什麼呢?因為他並不像 cp 一樣,可以直接的將檔案給他 copy 過去,例如 cp * /tmp 就可以將所在目錄的所有檔案 copy 到 /tmp 底下,在 cpio 這個指令的用法中,由於 cpio 無法直接讀取檔案,而是需要『每一個檔案或目錄的路徑連同檔名一起』才可以被記錄下來!因此, cpio 最常跟 find 這個指令一起使用了!這個 cpio 好像不怎麼好用呦!但是,嘿嘿!他可是備份的時候的一項利器呢!因為他可以備份任何的檔案,包括 /dev 底下的任何裝置檔案!呵呵!所以他可是相當重要的呢!!您說是吧! 而由於 cpio 必需要配合其他的程式,例如 find 來建立檔名,所以, cpio 與管線命令及命令重導向的相關性就相當的重要了!上面的例子剛好可以用來複習一下上一章節裡面提到的內容!加油啦!
     
    • 備份:在備份的用法當中,他可以直接跟輸出到檔案或者是裝置當中,但是如前面說過的,你必須要配合 find 這個指令較好呦!那個 -o 表示將檔案或目錄輸出到右邊去的意思!還記得命令重導向嗎?對啦!就是那個東西囉!在上面的例子中,我們將備份的資料給他 copy 到磁帶機裡頭去!那個磁帶機的裝置代號就是 /dev/st0 囉!
     
    • 還原:那麼如何給他反過來解開呢?呵呵!可以直接給他下達 cpio -i 就是 input 就對啦!例如上頭的例子囉!這個指令可以多看看呢
修改歷史:
  • 2003/02/09:第一次完成
  • 2003/05/05:修改 tar 的部分內容,尤其是 -P 這個參數的配合用法
伺服器篇文件
各版本彙整說明
CentOS 6.x