cpio归档工具的用法详细说明
cpio归档工具的用法详细说明
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的一个特殊用法:它从标准输入中读取待拷贝内容,然后将它们复制到目标路径下。
cpio命令用法说明
对于cpio这个归档工具来说,它和其它命令有一个区别:在cpio命令行中给出的非选项参数都会认为是pattern。
非选项参数的意思是这个参数不是为选项指定的参数。如cpio -t abc <a.cpio
中,-t
选项的功能是列出文件列表,它不需要参数,但后面给定了abc,则表示列出匹配abc的文件或目录。
1 | 选项说明: |
cpio使用示例
(1).将家目录下的所有文件都归档到tree.cpio中。
1 | $ find ~ -depth | cpio -ov > tree.cpio |
要注意一点,如果使用find搜索,且归档文件和搜索目录是同一路径时,它会将归档文件本身也归档到归档文件中,即进行了迭代归档。
例如上面的例子中,将find家目录的所有文件都归档到tree.cpio,但tree.cpio也将是放在家目录下的,它也会被find 搜索到,所以也会被归档到其自身中去。可能这里会有所疑惑了,不是应该find处理完之后才处理cpio吗?非也,管道的作用只是进程间数据传递的作用,但不是一定要等管道左边的处理完成之后才传递,而是左边边处理边传递到右边的,如果左边处理的太快,将导致管道拥堵,那么管道左边的程序将等待管道有空闲空间。
要解决迭代归档的问题,只要让归档文件不被find搜索到即可。可以在find中排除、在cpio中排除或归档文件放到其他目录下去。
1 | $ find ~ -depth | cpio -ov -F /tmp/tree.cpio |
一般出于准确性考虑,会在find上使用-print0
,然后在cpio上使用--null
解析空字符。
1 | $ find ~ -depth -print0 | cpio --null -ov -F /tmp/tree.cpio |
(2).列出归档文件中的文件列表。
1 | $ cpio -t -F tree.cpio |
这将会递归列出tree.cpio中的所有文件,所以这不会是你想要的,应该对其指定一个匹配模式。
1 | $ cpio -t -F tree.cpio /root/* |
这将列出tree.cpio中所有/root/目录下的内容,但是很显然,*
号没法匹配点开头的隐藏文件,所以不会显示出隐藏文件。
1 | $ cpio -t -F tree.cpio /root/.* |
但这样又只会列出隐藏文件。如何既列出隐藏文件,也列出普通文件?如下:
1 | $ cpio -t -F tree.cpio /root/{.*,*} |
注意,cpio命令行中任意非选项参数都会被当成pattern。
(3).向归档文件中追加文件。
注意,不要使用重定向符号>>
进行追加,虽然从归档文件最后的大小上看是追加成功了,但实际上你却不知道它追加到哪里去了。所以,还是用-A
选项。
1 | $ ls /root/new.txt | cpio -oA -F tree.cpio |
这将会把/root/new.txt下的文件追加到tree.cpio中,由于tree.cpio中已经有了/root目录,所以追加后路径为tree.cpio中的/root/new.txt。
而如果tree.cpio中没有待追加文件所在的目录,则会新建一个目录。
1 | $ find /boot -depth -print0 | cpio -oA -F tree.cpio |
这将会在tree.cpio中追加一个/boot目录,它和/root目录是同级别的。
(4).提取文件。
注意:cpio只能提取文件时只能提取到当前目录下。
1 | $ cpio -idv -F tree.cpio /root/new.txt |
这会提取/root/下的new.txt到当前目录,显然,这里报了一个错,提示当前目录下已经存在较待提取文件更新的同名文件,所以并没有进行提取。如果要强行提取,使用功能-u
选项,这将覆盖已存在动作。
1 | $ cpio -idvu -F tree.cpio new.txt |
其实,只要是同名文件,不管它的时间戳是否比待提取更新,都不会提取,除非强制提取。
这里-d
选项的作用是提取时如果前导目录不存在,则自动创建。反正不会影响已存在目录,所以-i
一般都会加上个-d
。
(5).目录文件复制,即copy-pass模式。
注意,该模式下复制的目录在目标位置上是以子目录形式存在的。例如,例如复制/root目录到/tmp/abc下,则在/tmp/abc下会有root子目录,在/tmp/abc/root下才是源/root中的文件。
1 | $ find ~ -depth -print0 | cpio --null -pvd /tmp/abc |