如何在 Linux 上创建和提取 cpio 档案示例
尽管 cpio 归档实用程序现在比其他归档工具(例如 tar)使用得更少,但了解它的工作原理仍然是件好事,因为它仍然被用于例如在 Linux 上创建 initramfs 映像以及rpm 软件包,主要用于 Red Hat 系列发行版。在本教程中,我们将了解如何使用 GNU cpio 实用程序创建和提取 cpio 存档,以及如何获取它们包含的文件列表。
在本教程中您将学习:
cpio 实用程序基础知识
如何创建 cpio 存档并可选择压缩它
如何提取 cpio 存档
如何获取 cpio 存档中包含的文件列表
使用的软件要求和约定
介绍cpio
cpio 代表“Copy In and Out”:正如我们已经说过的,它是一个归档实用程序,通常包含在所有 Unix 和类 Unix 操作系统(包括 Linux)中。 cpio 有两种主要的使用模式:“Copy-out”和“Copy-in”。在前一种模式下,应用程序从标准输入读取文件名列表,并默认创建一个存档到标准输出;当在后一种模式中使用时,它会从存档中复制文件。还有另一种模式,“copy-pass”,但我们在本教程中不会讨论它。
创建存档(复制输出模式)
cpio 本身没有探索目录树的能力,因此,与我们使用 tar 所做的不同,我们不能将目录作为参数传递并期望 cpio 递归地创建包含其所有内容的存档。相反,本着“做一件事并做好”的 Unix 精神,我们必须使用另一个实用程序,例如 find
来创建要包含在存档中的文件列表。让我们看一个例子。
假设我们要使用主目录的内容创建一个 cpio 存档。这是我们可以启动的命令:
$ find "$HOME" -depth -print0 | cpio -ocv0 > /tmp/archive.cpio
我们来分析一下上面我们做了什么。我们使用 find
实用程序来获取应成为存档一部分的文件列表。作为该实用程序的第一个参数,我们传递了应存档其内容的目录路径,并使用了两个选项:-deep
和 -print0
.前者修改了 find
的行为,以便在目录本身之前处理每个目录内容;为什么需要这个?
假设文件和目录被 find
正常处理(顶部优先),并且我们有一个只读目录。如果此目录在其包含的文件之前被处理,则它将在它们之前放入存档中,并在请求时在它们之前提取。由于cpio没有管理文件和目录权限的能力,并且目录是只读的,因此一旦恢复就无法复制其中的文件。
相反,使用 -print0
选项,我们将完整的文件名打印在标准输出上,并用 null 字符而不是标准新行分隔。这是一种让我们包含名称中包含换行符的文件的措施。
我们将 find 的输出通过管道传输到 cpio 标准输入,以便列表中的文件包含在存档中。运行 cpio 时,我们使用了 -o
、-v
、-c
和 -0
选项。第一个是 --create
的缩写形式,需要指定我们要在“copy-out”模式下使用 cpio。 -v
选项 (--verbose
) 用于列出应用程序正在处理的文件,并使用 -c
我们指定要使用的 cpio 格式。在复制输出模式下运行以创建存档时,默认情况下使用非常旧的“bin”格式。使用 -c
基本上是 -H newc
的简写(-H
选项让我们指定 cpio 格式),这使得 cpio使用新的SVR4便携式格式。最后,我们使用了-0
选项,它是--null
的缩写形式。最后一个选项用于指定列表中的文件由空字符分隔。
我们做的最后一件事是将 cpio 的输出重定向到一个文件,我们令人惊讶地将该存档命名为 /tmp/archive.cpio
(文件扩展名完全是任意的)。作为最后一个重定向的替代方案,我们可以使用 cpio -F
选项 (--file
) 并以文件名作为参数,指示应用程序写入该文件而不是标准输出。
如果我们需要在创建时压缩存档怎么办?我们可以简单地使用另一个管道将 cpio 标准输出传递到另一个专门设计用于压缩文件的应用程序,例如 gzip。我们会写:
$ find "$HOME" -depth -print0 | cpio -ocv0 | gzip -9 > /tmp/archive.cpio.gz
提取存档(拷入模式)
我们刚刚了解了如何创建 cpio 存档,现在让我们看看如何提取一个。我们应该说的第一件事是,在复制输出模式下,我们需要指定要使用的存档格式(如果我们想使用与默认“bin”不同的东西),在提取时,该格式会自动识别。
为了使 cpio 在copy-in模式下运行,我们使用-i
选项启动cpio实用程序,该选项是--extract
的缩写。在此模式下工作时,我们需要将存档作为 cpio 标准输入传递。以下是我们提取之前创建的存档的方法:
$ cpio -iv < /tmp/archive.cpio
运行此命令时,存储在存档中的文件将被提取到当前工作目录中。如果文件系统上已存在更新或相同版本的文件,cpio 将拒绝提取它们,并返回类似于以下内容的错误:
<file> not created: newer or same age version exists
如果我们想在执行实际提取之前切换到另一个位置,我们所要做的就是使用 -D
选项(--directory
的缩写)指定它。
就像在copy-out模式下工作一样,我们可以使用-F
选项指示cpio从标准输入之外的文件中读取,以文件名作为参数。
如果我们要提取的存档是压缩的怎么办?假设我们想要提取使用 gzip 压缩的存档,我们需要首先读取压缩数据,然后将其通过管道传递给 cpio。对于 gzip 压缩文件,我们可以使用 zcat 实用程序来执行此类任务:
$ zcat /tmp/archive.cpio.gz | cpio -iv
列出 cpio 存档中包含的文件
无需解压即可获取 cpio 存档中包含的文件列表,这非常简单。与 -t
选项一起运行应用程序就足够了,该选项是 --list
的缩写形式。举个例子,要列出我们在本教程第一部分中创建的存档中的所有文件,我们将运行:
$ cpio -t < /tmp/archive.cpio
该命令会生成存储在存档中的文件列表。如果我们向其添加 -v 选项,我们将获得类似于 ls -l 的输出,其中包括文件和目录权限。
结论
在本文中,我们学习了如何在 Linux 上使用 cpio 实用程序。虽然现在它比 tar 更少使用,但了解它的工作原理很重要,因为它仍然用于特定目的,例如创建 rpm 软件包。我们了解了如何创建存档、如何提取存档以及最后如何列出其内容。