tar命令基本、進階使用指北
摘要
打包與壓縮是我們在計算機系統日常使用中必備的一個工具,就如我們在使用Windows系統,也需要類似WinRAR的壓縮軟體來將許多資料、檔案打包成一個檔案,並壓縮其佔用空間。我們在Linux下也需要這樣的工具,Linux下有類似gzip、bzip2之類的壓縮工具,不過,這兩個命令對目錄的壓縮指的是將目錄內的所有檔案“分別”進行壓縮。
那Linux下有沒有類似WinRAR一樣強大的打包工具呢?那就是大名鼎鼎的tar了。tar可以將多個目錄或檔案打包成一個大檔案,同時還可以通過gzip/bzip2的支援,將該檔案同時進行壓縮。更有趣的是,由於tar的使用太廣泛了,以致於目前WinRAR也支援tar.gz檔名的解壓縮。本文我將介紹tar命令的語法構成、引數說明、具體使用以及進階操作。
一、語法構成與引數說明
1. tar
語法構成
tar的引數非常多,這裡只講幾個常用引數,更多引數可通過man tar
查詢。
[root@centos7-master ~]# tar [-j|-z] [cv] [-f 新建的檔名] filename... <==打包與壓縮
[root@centos7-master ~]# tar [-j|-z] [tv] [-f 新建的檔名] <==檢視檔名
[root@centos7-master ~]# tar [-j|-z] [xv] [-f 新建的檔名] [-C 指定目錄] <==解壓縮
2. tar
引數說明
-j:通過bzip2的支援進行壓縮/解壓縮,此時檔名最好為*.tar.bz2,這種壓縮方式效果比gzip壓縮效果更好(壓縮後的檔案更小)
-z:通過gzip的支援進行壓縮/解壓縮,此時檔名最好為*.tar.gz
-c:新建打包檔案,可搭配 -v 來檢視過程中被打包的檔名(filename)
-t:檢視打包檔案的內容含有哪些檔名,重點在檢視檔名。
-x:解打包或解壓縮的功能,可以搭配 -C(大寫)在特定目錄解開。
特別留意:-c、-t、-x 不可同時出現在一串命令列中。
-v:在壓縮/解壓縮的過程中,將正在處理的檔名顯示出來
-f filename:-f 後面要接被處理的檔名,建議 -f 單獨寫一個引數
-C 指定目錄:這個引數用在解壓縮時,若要在特定目錄解壓縮,可以使用這個引數
-p:保留備份資料原本許可權與屬性,常用於備份(-c)重要的配置檔案
-P:保留絕對路徑,即允許備份資料中包含有根目錄/
-exclude=FILE: 在壓縮過程中,排除FILE,不要將FILE打包
3. tarfile與tarball的區別
我們知道tar
是一個打包&壓縮命令,它支援僅打包而不壓縮,也支援即打包又壓縮。
如果僅打包,就是tar -cv -f file.tar
而已,這個檔案我們稱為tarfile
。
如果即打包又壓縮,就是tar -jcv -f file.tar.bz2
而已,這個檔案我們稱為tarball
。
二、tar
的具體使用
tar最常用的三個命令形式如下:
打包:tar -cv -f filename.tar filename
壓縮:tar -jcv -f filename.tar.bz2 filename
tar -zcv -f filename.tar.gz filename
查詢:tar -jtv -f filename.tar.bz2
解壓縮:tar -jxv -f filename.tar.bz2 -C 指定解壓縮目錄
這裡說明一下,-f filename
是緊接在一起的,但很多文章會寫成-jcvf filename
,這樣也是對的。但由於引數的順序理論上可調整,有些同學會寫成-jvfc filename
,其實也可以執行,但是會導致產生的檔名變為x,因為f
後面緊跟的是c
,系統會將f
後面的內容識別為檔名。
所以建議還是把-f filename
與其他引數獨立開來寫,可以避免不必要的問題出現。
但經過在Centos7上的實驗,若引數f
不寫在最後(filename前面),會無法執行,說明Centos7對tar
命令做了優化處理,具體如下:
[root@centos7-master ~]# tar -jvfc test_tar.tar.bz2 ./test_tar
tar: You must specify one of the `-Acdtrux' or `--test-label' options
Try `tar --help' or `tar --usage' for more information.
三、tar
進階
1. -p
引數:保留檔案的許可權與屬性資訊,且去掉根目錄進行打包&壓縮
使用tar -p
保留備份資料的原本許可權與屬性。下面以備份etc
目錄為例:
[root@centos7-master ~]# tar -jpcv -f /root/etc.tar.bz2 /etc
tar: Removing leading `/' from member names <==注意這個警告訊息
# -p引數會保留原文字檔案的許可權與屬性
我們查閱一下剛剛備份的etc目錄長什麼樣。
[root@centos7-master ~]# tar -jtv -f /root/etc.tar.bz2
...前面省略...
-rw-r--r-- root/root 2000 2019-08-06 21:44 etc/ntp.conf
drwxr-xr-x root/root 0 2020-05-01 20:25 etc/smartmontools/
-rw-r--r-- root/root 6774 2020-04-01 12:32 etc/smartmontools/smartd.conf
drwxr-xr-x root/root 0 2020-04-01 12:32 etc/smartmontools/smartd_warning.d/
-rwxr-xr-x root/root 5586 2020-04-01 12:32 etc/smartmontools/smartd_warning.sh
我們發現一個有趣的事情,那就是每個檔名都沒了根目錄。這也是上面我們在打包etc
目錄時遇到的那個警告訊息tar: Removing leading `/' from member names
(刪除了檔名開頭的`/')所告知的情況。
那為什麼要去掉根目錄呢?
主要是為了安全。我們知道,使用tar備份的資料可能會需要解壓縮回來使用,tar -jtvf
命令所檢視到的檔名就是解壓縮後的實際檔名。
設想一下,如果沒有去掉根目錄,解壓縮後的檔名就會是絕對路徑,即解壓縮後的資料一定會被放置到/etc/xxx
去。如此一來,系統原本的/etc/
下面的資料就會被備份資料所覆蓋掉了,這是一件很可怕的事情。
但如果我們在壓縮的時候使用-p
引數,即可去掉根目錄,假設我們將備份資料在/tmp
中解開,那麼解壓縮後檔案所在的路徑就會是/tmp/etc/xxx
。這樣系統本身的/etc/
就不會被覆蓋了~
2. -P
引數:保留根目錄進行打包&壓縮
如果你確實有需要備份根目錄到tar檔案中,那可以使用-P
(大寫)引數。
[root@centos7-master ~]# tar -jpPcv -f /root/etc.and.root.tar.bz2 /etc
...省略中間過程...
[root@centos7-master ~]# tar -jtf /root/etc.and.root.tar.bz2
...省略前面的輸出...
/etc/smartmontools/
/etc/smartmontools/smartd.conf
/etc/smartmontools/smartd_warning.d/
/etc/smartmontools/smartd_warning.sh
可以看到,使用-P
引數後,檔名內的根目錄就會存在。
3.僅解壓單一檔案的方法
(1) 找到我們想要的檔名,如shadow檔案
[root@centos7-master ~]# tar -jtv -f /root/etc.tar.bz2 | grep 'shadow'
---------- root/root 422 2020-05-01 20:34 etc/gshadow
---------- root/root 409 2020-05-01 20:25 etc/gshadow-
---------- root/root 786 2020-05-01 20:34 etc/shadow <==這是我們要的
---------- root/root 762 2020-05-01 20:25 etc/shadow-
(2) 將該檔案解開,語法與實際方法如下:
[root@centos7-master ~]# tar -jxv -f 打包的檔案.tar.bz2 待解開檔名
[root@centos7-master ~]# tar -jxv -f /root/etc.tar.bz2 etc/shadow
4. --exclede=FILE:
打包某目錄,但不包含某些檔案的方法
這裡我們打包/etc/ /root 這幾個目錄,但排除/root/etc*開發的檔案,排除我們本次打包新生成的檔案/root/system.tar.bz2(不要打包自己),以此為例。
[root@centos7-master ~]# tar -jcv -f /root/system.tar.bz2 --exclude=/root/etc* \
> --exclude=/root/system.tar.bz2 /etc /root
5. --newer-mtime=time
僅備份比time時刻還要新的檔案
(1) 先由find找出比/etc/passwd
還要新的檔案
[root@centos7-master ~]# find /etc -newer /etc/passwd
...過程省略...
# 此時會顯示出比/etc/passwd這個檔案的mtime還要新的檔名
[root@centos7-master ~]# ll /etc/passwd
-rw-r--r-- 1 root root 1107 May 1 20:34 /etc/passwd
(2) 使用tar進行打包,日期為上面看到的2020/05/01
[root@centos7-master ~]# tar -jcv -f /root/etc.newer.then.passwd.tar.bz2 \
> --newer-mtime="2020/05/01" /etc/*
...中間省略...
/etc/X11/
/etc/X11/applnk/ <==這些是成功備份的檔案
/etc/X11/fontpath.d/
...中間省略...
tar: /etc/yum.repos.d/CentOS-Vault.repo: file is unchanged; not dumped
tar: /etc/yum.repos.d/CentOS-fasttrack.repo: file is unchanged; not dumped #這些是沒有被備份的檔案
(3) 顯示出檔案
[root@centos7-master ~]# tar -jtv -f /root/etc.newer.then.passwd.tar.bz2 | \
> grep -v '/$'
#grep -v 表示排除掉符合後面所跟條件的檔案
6. 使用tar將檔案打包到某些特殊裝置中
磁帶機(tape)由於是一次性讀取/寫入裝置,因此我們不能夠使用類似cp
等命令來複制。如果想要將/home
,/etc
,/root
備份到磁帶機(/dev/st0
)時,可以用以下命令:
[root@centos7-master ~]# tar -cv -f /dev/st0 /home /root /etc
7. 特殊應用:利用管道命令與資料流
tar
有一種特殊的使用方式,那就是通過標準輸入輸出的資料流重定向(standard input/standard output
),以及管道命令(pipe
)的方式,將待處理的檔案一邊打包一邊解壓縮到目標目錄去。
# 將/etc整個目錄一邊打包一邊在/tmp中解開
[root@centos7-master ~]# cd /tmp
[root@centos7-master ~]# tar -cvf - /etc | tar -xvf -
# 要注意到,前面的壓縮命令中,輸入檔案變成 - ;後面的解壓縮命令中,輸出命令也變成 - ;且中間有 | 作為管道
# 對於 - 的理解,可以將 - 想象成在記憶體中的一個裝置(緩衝區—)
# 這種方式類似於cp -r /etc /tmp 但無需中間檔案存在,可以將其看作是另一種方式進行復制的行為
參考文獻
[1] 鳥哥(著).王世江(改編).鳥哥的Linux私房菜基礎學習篇[M].北京:人民郵電出版社,2010.254-258
[2] Sam哥哥.Linux grep -v 命令排除輸出[DB/OL].https://blog.csdn.net/linsongbin1/article/details/90515091, 2019-05-24/2020-05-03