1.1 cpio基本介紹
cpio是一個非常古老的歸檔工具。已逐漸被tar替代,但是有些功能是tar不存在的,所以還是分享下它的用法。
cpio - copy files to and from archives
cpio用於創建、解壓歸檔文件,也可以對歸檔文件執行拷入拷出的動作,即向歸檔文件中追加文件,或從歸檔文件中提取文件。它也支持tar格式的歸檔文件,但是對壓縮后的tar(如.tar.gz格式)就沒法支持了,cpio畢竟不會調用對應的(解)壓縮工具。
cpio一般從標准輸入獲取數據,寫入到標准輸出,所以一般會結合管道、輸入重定向、輸出重定向使用。
cpio有三種運行模式:
Copy-out模式:此模式下,cpio將向歸檔文件中拷入文件,即進行歸檔操作,所以成為歸檔模式。它會從標准輸入中讀取待歸檔的文件,將它們歸檔到目標目標中,若未指定歸檔的目標,將歸檔到標准輸出中。在copy-out模式下,最典型的是使用find來指定待歸檔文件,在使用find時,最好加上"-depth"以盡可能減少可能出現的問題,例如目錄的權限問題
Copy-in模式:此模式下,cpio將從歸檔文件中提取文件,或者列出歸檔文件中的文件列表。它將從標准輸入中讀取歸檔文件。任意cpio的非選項參數都將認為是shell的glob通配pattern,只有文件名匹配了指定模式時才會從中提取出來或list出來。在cpio中,通配符不能匹配到"."或"/",所以如有需要,必須顯式指定"."或"/"。如果沒有指定匹配模式,則解壓或列出所有文件。
Copy-pass模式:此模式下,cpio拷貝一個目錄樹(即目錄中所有文件)到另一個目錄下,並在目標目錄下以同名的子目錄存在。copy-pass模式是copy-in模式再copy-out模式的結合,它中途沒有涉及到任何歸檔行為。這是cpio的一個特殊用法。它從標准輸入中讀取待拷貝內容,然后將它們復制到目標路徑下。
1.2 cpio命令用法說明
對於cpio這個歸檔工具來說,它和其它命令有一個區別:在cpio命令行中給出的非選項參數都會認為是pattern。非選項參數的意思是這個參數不是為選項指定的參數。如cpio -t abc <a.cpio中,"-t"選項的功能是列出文件列表,它不需要參數,但后面給定了abc,則表示列出匹配abc的文件或目錄。
選項說明:
-o:(--create)指定運行為copy-out模式,即歸檔模式
-i:(--extract)指定運行為copy-in模式,即提取模式
-p:(--pass-through)指定運行為copy-pass模式,即目錄拷貝模式
-t:(--list)列出歸檔文件中的文件列表
-B:設置I/O的block大小為5120字節,默認為512字節
-C IO-SIZE:(--io-size=IO-SIZE)指定I/O的block大小為IO-SIZE大小
-I archive:使用指定的歸檔文件名替代標准輸入(從標准輸入讀取的,所以肯定是解壓模式,即copy-in)
-O archive:使用指定的歸檔文件名替代標准輸出(輸出到標准輸出的,所以肯定是歸檔模式,即copy-out)
-F archive:(--file=archive)使用指定的歸檔文件名替代標准輸入或輸出。所以無論是copy-in還是copy-out模式都可以使用-F指定歸檔文件
:注意copy-out即歸檔模式下,其默認行為等價於重定向符號">",所以內容會完全覆蓋,但歸檔文件(inode)不變
-A:(--append)向已存在的歸檔文件中追加文件,只能使用-F或-O指定歸檔文件,只能用在copy-out模式下。不等價於重定向符號">>",">>"后在歸檔文件中找不到追加的文件
--to-stdout:解壓文件到標准輸出,用在copy-in模式
-E FILE:(--pattern-file=FILE)從FILE中讀取pattern進行匹配,匹配到的將解壓或列出它們,用在copy-in模式。
-f:(--nonmatching)僅copy不匹配指定pattern的文件
-u:(--unconditional)當目標中有同名文件時,強制替換沖突文件
-a:(--reset-access-time)重置文件的atime,即保留文件的原始atime
-m:(--preserve-modification-time)保留文件的原始mtime
-d:(-make-directories)當需要的時候自動創建目錄
-0:(--null)解析空字符串\0
--quiet:不輸出拷貝時的block數量信息
-v:給出詳細信息
1.3 示例
(1).將家目錄下的所有文件都歸檔到tree.cpio中。
但要非常注意一點,如果使用find搜索,且歸檔文件和搜索目錄是同一路徑時,它會將歸檔文件本身也歸檔到歸檔文件中,即進行了迭代歸檔。
例如上面的例子中,將find家目錄的所有文件都歸檔到tree.cpio,但tree.cpio也將是放在家目錄下的,它也會被find搜素到,所以也會被歸檔到其自身中去。可能這里會有所疑惑了,不是應該find處理完之后才處理cpio嗎?非也,管道的作用只是進程間數據傳遞的作用,但不是一定要等管道左邊的處理完成之后才傳遞,而是左邊邊處理邊傳遞到右邊的,如果左邊處理的太快,導致管道擁堵,那么管道左邊的程序將等待管道有空閑空間。
要解決迭代歸檔的問題,只要讓歸檔文件不被find搜索到即可。可以在find中排除、在cpio中排除或歸檔文件放到其他目錄下去。
一般出於准確性考慮,會在find上使用"-print0",然后在cpio上使用"--null"解析空字符。
(2).列出歸檔文件中的文件列表。
這將會遞歸列出tree.cpio中的所有文件,所以這不會是你想要的,應該對其指定一個匹配模式。
[root@server2 tmp]# cpio -t -F tree.cpio /root/* 或 [root@server2 tmp]# cpio -t /root/* < tree.cpio
這將列出tree.cpio中所有/root/目錄下的內容,但是很顯然,"*"號沒法匹配點開頭的隱藏文件,所以不會顯示出隱藏文件。
但這樣又只會列出隱藏文件。如何既列出隱藏文件,也列出普通文件?在cpio中好像不直接支持這樣的通配,以下是我想到的一個辦法。
注意,cpio命令行中任意非選項參數都會被當成pattern。
(3).向歸檔文件中追加文件。
注意,不要使用重定向符號">>"進行追加,雖然從歸檔文件最后的打下上看是追加成功了,但是實際上你卻不知道它追加到哪里去了,根本就找不到追加的內容。所以,還是用"-A"選項。
這將會把/root/new.txt下的文件追加到tree.cpio中,由於tree.cpio中已經有了/root目錄,所以追加后路徑為tree.cpio中的/root/new.txt。
而如果tree.cpio中沒有待追加文件所在的目錄,則會新建一個目錄。
這將會在tree.cpio中追加一個/boot目錄,它和/root目錄是同級別的。
好像沒有辦法直接指定追加的目標路徑。
(4).提取文件。
注意:cpio只能提取文件時只能提取到當前目錄下。
new.txt cpio: new.txt not created: newer or same age version exists
這就會提取/root/下的new.txt到當前目錄,顯然,這里報了一個錯,提示當前目錄下已經存在較待提取文件更新的同名文件,所以並沒有進行提取。如果要強行提取,使用功能"-u"選項,這將覆蓋已存在動作。
其實,只要是同名文件,不管它的時間戳是否比待提取更新,都不會提取,除非強制提取。
這里"-d"選項的作用是提取時如果前導目錄不存在,則自動創建。反正不會影響已存在目錄,所以"-i"一般都會加上個"-d"。
(5).目錄文件復制,即copy-pass模式。
注意,該模式下復制的目錄在目標位置上是以子目錄形式存在的。例如,例如復制/root目錄到/tmp/abc下,則在/tmp/abc下會有root子目錄,在/tmp/abc/root下才是源/root中的文件。