Learning Objectives
- 分辨「打包」與「壓縮」:tar 把很多檔案合成一個,gzip/bzip2/xz 把一個檔案變小
- 用 tar -cvf 打包、tar -tf 查看打包檔裡有什麼,了解 tar 會移除路徑開頭的 /
- 用 tar -czf/-cjf/-cJf 打包並壓縮,比較三種格式的大小
- 用 gzip、bzip2、xz 壓縮單一檔案,用 -k 保留原檔、-1~-9 調整壓縮等級;知道 gzip 不能直接壓縮目錄
打包與壓縮是兩件事
要把一整個專案目錄寄給別人或備份起來,通常會做兩件事:
| 動作 | 意思 | 工具 | 結果 |
|---|---|---|---|
| 打包(archive) | 把很多檔案與目錄合成一個檔案,保留目錄結構、權限與時間 | tar |
project.tar,大小和原本差不多 |
| 壓縮(compress) | 把一個檔案變小 | gzip、bzip2、xz |
project.tar.gz,大小明顯變小 |
Linux 的習慣是兩件事分開:tar 只負責打包,壓縮交給別的程式;tar 也可以加選項,一次完成「打包再壓縮」。
Windows 常見的 .zip 則是同時打包與壓縮的格式。
常見的副檔名:
| 副檔名 | 產生方式 |
|---|---|
.tar |
tar 打包,沒有壓縮 |
.gz、.bz2、.xz |
用 gzip、bzip2、xz 壓縮的單一檔案 |
.tar.gz(也寫成 .tgz)、.tar.bz2、.tar.xz |
先用 tar 打包,再用對應的程式壓縮 |
.zip |
zip 程式,同時打包與壓縮 |
.Z |
早期 compress 程式的格式,現在很少見 |
打包之前,先用前幾課的指令整理檔案:
find . -name "*.txt"找出要的檔案、cp -v複製時顯示過程、mv -i移動前詢問、rm -rf刪除不要的目錄(不會詢問,下手前看清楚路徑)。
tar:打包與查看
tar -cvf 打包檔.tar 要打包的檔案或目錄...
| 選項 | 意思 |
|---|---|
-c |
create,建立新的打包檔 |
-t |
list,列出打包檔裡有哪些檔案 |
-x |
extract,解開打包檔(下一課說明) |
-v |
verbose,列出正在處理的檔案 |
-f 檔名 |
指定打包檔的名稱;f 後面要緊接著檔名,所以習慣把 f 放在選項的最後 |
-z、-j、-J |
打包後再用 gzip、bzip2、xz 壓縮 |
-c、-t、-x 三選一,不能同時用。幾個例子:
tar -cvf tmp.tar /tmp # 把 /tmp 打包成 tmp.tar
tar -cvf abc.tar /etc/samba/ /tmp # 一次打包好幾個目錄
tar -tf tmp.tar # 列出 tmp.tar 裡的所有檔案
tar -tf tmp.tar abc.php # 只列出名稱是 abc.php 的檔案
tar -tf tmp.tar --wildcards '*.php' # 用萬用字元比對,要加 --wildcards
GNU tar 從 1.15.91 版起,
-t與-x後面的檔名預設不當成萬用字元;投影片的tar -tf tmp.tar '*.php'會找名稱真的叫*.php的檔案,要加--wildcards才會比對所有.php檔。
為什麼會看到 Removing leading `/'
$ tar -cvf ghostscript.tar /etc/ghostscript/
tar: Removing leading `/' from member names
etc/ghostscript/
etc/ghostscript/cidfmap.d/
...
這不是錯誤。tar 把絕對路徑開頭的 / 拿掉,打包檔裡存的是 etc/ghostscript/... 這種相對路徑。
解開時檔案就會放在「目前所在目錄」底下的 etc/ghostscript/,不會直接覆蓋系統真正的 /etc/ghostscript/。
tar 至少要給一個要打包的對象,什麼都沒給會出現:
tar: Cowardly refusing to create an empty archive
打包再壓縮:-z、-j、-J
| 指令 | 壓縮程式 | 副檔名 | 特色 |
|---|---|---|---|
tar -czf gs.tar.gz /etc/ghostscript |
gzip | .tar.gz |
速度快、到處都能解,最常見 |
tar -cjf gs.tar.bz2 /etc/ghostscript |
bzip2 | .tar.bz2 |
通常比 gzip 小一些、比較慢 |
tar -cJf gs.tar.xz /etc/ghostscript |
xz | .tar.xz |
文字類的大檔案通常壓得最小,壓縮最慢 |
注意 -J 是大寫,小寫 -j 是 bzip2。壓縮後用 ls -l 或 ls -lh 比較大小。
下面練習裡的檔案大小是模擬器的示意值。實際的大小依內容而定;檔案很小時,各格式的檔頭本身就占了不少位元組,順序不一定是 xz 最小。
gzip、bzip2、xz:壓縮單一檔案
三個程式的用法幾乎一樣:
gzip 檔案 # 產生 檔案.gz,原檔被取代(消失)
bzip2 檔案 # 產生 檔案.bz2
xz 檔案 # 產生 檔案.xz
| 選項 | 意思 |
|---|---|
-k |
keep,保留原檔(gzip 1.6 版以後才有;Ubuntu 24.04 的 gzip 是 1.12) |
-v |
顯示壓縮比 |
-d |
解壓縮(等於 gunzip、bunzip2、unxz,下一課說明) |
-c |
把壓縮結果輸出到螢幕(標準輸出),原檔不動,可以搭配重導:gzip -c a.txt > a.txt.gz |
-1~-9 |
壓縮等級:-1 最快但壓得最少,-9 最慢但壓得最小;gzip 預設 -6 |
-t |
檢查壓縮檔是否完整 |
gzip -l、xz -l |
列出壓縮檔的壓縮前後大小 |
$ gzip /etc/ghostscript
gzip: /etc/ghostscript is a directory -- ignored
gzip、bzip2、xz 只處理單一檔案,不能把整個目錄壓成一個檔案(gzip -r 會把目錄裡的檔案一個一個分別壓縮,不是合成一個)。
要壓縮整個目錄,先用 tar 打包,也就是 tar -czf。
zip:和 Windows 交換檔案
zip -r logs.zip logs # -r 把整個目錄放進 zip
Ubuntu Server 可能沒有預先安裝 zip 與 unzip,出現 Command 'zip' not found 時用 sudo apt install zip unzip 安裝(APT 在第 19 課說明)。
想一想:打包
關於 tar -cvf project.tar project/,下列何者正確?
tar -czf etc.tar.gz /etc 出現 Removing leading '/' from member names,代表什麼?
想把目錄打包並用 xz 壓縮,選項要怎麼寫?
想一想:壓縮
執行 gzip report.txt 之後,目錄裡會有什麼?
gzip photos(photos 是目錄)出現 photos is a directory -- ignored,應該怎麼做才能得到一個壓縮檔?
關於壓縮等級 -1 到 -9,下列何者正確?
重點精華回顧
- 打包(
tar)把很多檔案合成一個;壓縮(gzip、bzip2、xz)把一個檔案變小。.tar.gz就是先打包再壓縮。 tar -cvf a.tar 目錄打包、tar -tf a.tar列出內容;-f後面接檔名。tar會移除路徑開頭的/,解開時檔案放在目前目錄底下。-z(gzip)、-j(bzip2)、-J(xz)讓 tar 一次完成打包與壓縮;文字類的大檔案通常 xz 最小、gzip 最快。gzip、bzip2、xz預設取代原檔,-k保留原檔,-1~-9調整壓縮等級;它們不能把目錄壓成一個檔案。zip -r產生 Windows 也能直接開的.zip;沒有安裝時用sudo apt install zip unzip。