[ian@echidna lpi103-2]$ echo text* text1 text10 text2 text3 text4 text5 text6 [ian@echidna lpi103-2]$ echo "text*" text* [ian@echidna lpi103-2]$ echo text[[\!?]z?? text[[!?]z??
有关 globbing 的更多信息,请查阅 man 7 glob
。您将需要章节号,因为第 3 节中也介绍了 glob 信息。理解所有不同 shell 交互的最佳方式是进行实践,因此您需要多多尝试这些通配符。注意,在使用 cp
、mv
或 rm
出现异常行为之前,使用 ls
检查您的通配符模式。
回页首
我们现在来看看 touch
命令,它将更新文件访问和修改时间或创建空文件。在下一部分中,我们将探讨如何使用这些信息查找文件和目录。我们将继续在示例中使用 lpi103-2 目录。我们还将查看各种指定时间戳的方法。
不包含任何选项的 touch
命令使用一个或多个文件名作为参数,并将更新文件的修改时间。这个时间戳通常会和一个长目录列表一同显示。在清单 14 中,我们使用 echo
创建了一个小文件 f1,然后使用一个长目录列表来显示修改时间(即 mtime)。在本例中,修改时间正好是文件的创建时间。我们随后使用 sleep
命令来等待 60 秒,并在此运行 ls
。注意,该文件的时间戳已经修改了一段时间。
[ian@echidna lpi103-2]$ echo xxx>f1; ls -l f1; sleep 60; touch f1; ls -l f1 -rw-rw-r--. 1 ian ian 4 2009-08-14 18:24 f1 -rw-rw-r--. 1 ian ian 4 2009-08-14 18:25 f1
如果为一个并不存在的文件指定文件名,那么 touch
通常会为您创建一个空文件,除非您指定了 -c
或 --no-create
选项。清单 15 展示了这两个命令。注意,只有 f2 被创建。
[ian@echidna lpi103-2]$ touch f2; touch -c f3; ls -l f* -rw-rw-r--. 1 ian ian 4 2009-08-14 18:25 f1 -rw-rw-r--. 1 ian ian 0 2009-08-14 18:27 f2
touch
命令还可以将文件的修改时间(也称为 mtime)设置为一个特定日期和时间,可以使用 -d
或 -t
选项。-d
可以非常灵活地处理它将接受的日期和时间格式,而 -t
选项需要至少一个 MMDDhhmm 时间,年份和秒数是可选的。清单 16 展示了一些例子。
[ian@echidna lpi103-2]$ touch -t 200908121510.59 f3 [ian@echidna lpi103-2]$ touch -d 11am f4 [ian@echidna lpi103-2]$ touch -d "last fortnight" f5 [ian@echidna lpi103-2]$ touch -d "yesterday 6am" f6 [ian@echidna lpi103-2]$ touch -d "2 days ago 12:00" f7 [ian@echidna lpi103-2]$ touch -d "tomorrow 02:00" f8 [ian@echidna lpi103-2]$ touch -d "5 Nov" f9 [ian@echidna lpi103-2]$ ls -lrt f* -rw-rw-r--. 1 ian ian 0 2009-07-31 18:31 f5 -rw-rw-r--. 1 ian ian 0 2009-08-12 12:00 f7 -rw-rw-r--. 1 ian ian 0 2009-08-12 15:10 f3 -rw-rw-r--. 1 ian ian 0 2009-08-13 06:00 f6 -rw-rw-r--. 1 ian ian 0 2009-08-14 11:00 f4 -rw-rw-r--. 1 ian ian 4 2009-08-14 18:25 f1 -rw-rw-r--. 1 ian ian 0 2009-08-14 18:27 f2 -rw-rw-r--. 1 ian ian 0 2009-08-15 02:00 f8 -rw-rw-r--. 1 ian ian 0 2009-11-05 00:00 f9
如果您不确定某个日期表达式所表示的日期,那么可以使用 date
命令确定日期。它还接受 -d
选项并解析与 touch
相同的日历格式。
可以使用 -r
(或 --reference
)选项以及一个引用文件名 来表示 touch
(或 date
)应当使用现有文件的时间戳。清单 17 给出了一些示例。
[ian@echidna lpi103-2]$ date Fri Aug 14 18:33:48 EDT 2009 [ian@echidna lpi103-2]$ date -r f1 Fri Aug 14 18:25:50 EDT 2009 [ian@echidna lpi103-2]$ touch -r f1 f1a [ian@echidna lpi103-2]$ ls -l f1* -rw-rw-r--. 1 ian ian 4 2009-08-14 18:25 f1 -rw-rw-r--. 1 ian ian 0 2009-08-14 18:25 f1a
Linux 系统同时记录文件修改 时间和文件访问 时间。这两个时间也分别被称为 mtime 和 atime。当文件被创建时,这两个时间戳均被设置为相同的值,在文件被修改时,两个值同时被重置。如果文件被访问过,那么访问时间将被更新,即使文件未被修改。对于我们的最后一个 touch
例子,我们将查看文件访问 时间。-a
(或 --time=atime
、--time=access
或 --time=use
)选项表示访问时间应该被更新。清单 18 使用 cat
命令访问 f1 文件并显示其内容。我们随后使用 ls -l
和 ls -lu
分别显示 f1 和 f1a 的修改和访问时间,f1a 是使用 f1 作为引用文件创建的。我们随后使用 touch -a
将 f1 的访问时间重置为 f1a 的访问时间,然后检验它是否被重置。
[ian@echidna lpi103-2]$ ls -lu f1* -rw-rw-r--. 1 ian ian 4 2009-08-14 18:39 f1 -rw-rw-r--. 1 ian ian 0 2009-08-14 18:25 f1a [ian@echidna lpi103-2]$ ls -l f1* -rw-rw-r--. 1 ian ian 4 2009-08-14 18:25 f1 -rw-rw-r--. 1 ian ian 0 2009-08-14 18:25 f1a [ian@echidna lpi103-2]$ touch -a -r f1a f1 [ian@echidna lpi103-2]$ ls -lu f1* -rw-rw-r--. 1 ian ian 4 2009-08-14 18:25 f1 -rw-rw-r--. 1 ian ian 0 2009-08-14 18:25 f1a
有关大量可用日期和时间规范的更多完整信息,请参考手册或信息页中有关 touch
和 date
命令的内容。
回页首
现在我们已经介绍了文件和目录主题中的递归和 globbing 内容,递归涉及文件的所有方面,而 globbing 更具有针对性,让我们看看 find
命令,该命令更像是外科医生的手术刀。find
命令用于根据名称、时间戳或大小等条件查找一个或多个目录树中的文件。我们再一次使用 lpi103-2 目录。
find
命令将使用全名或部分名称搜索文件或目录,或者按照其他搜索条件搜索,例如大小、类型、文件所有者、创建日期或最近一次的访问时间。最基本的查找是按全名或部分名称查找。清单 19 展示了 lpi103-2 目录中的一个例子,我们将查找文件名中包含 '1' 或 'k' 的所有文件,然后执行一些路径搜索,下面的说明部分将加以解释。
[ian@echidna lpi103-2]$ find . -name "*[1k]*" ./f1a ./f1 ./text10 ./backup ./backup/text1.bkp.1 ./backup/text1.bkp.2 ./text1 [ian@echidna lpi103-2]$ find . -ipath "*ACK*1" ./backup/text1.bkp.1 [ian@echidna lpi103-2]$ find . -ipath "*ACK*/*1" [
说明:
您可以使用 shell 通配符模式,比如前面 通配符和 globbing 小节中的模式。
可以使用 -path
代替 -name
来匹配完全路径而不是基本文件名。在本例中,模式可能跨越路径组件,这与普通通配符匹配不同,后者只匹配路径的某个部分。
如果希望进行不区分大小写的搜索,如前面的 ipath
所示,那么在搜索字符串或模式的 find
选项前面加一个 'i'。
如果希望搜索名称以点开头的文件或目录名,比如 .bashrc 或当前目录 (.),那么您必须将一个前导圆点指定为模式的一部分。否则,名称搜索将忽略这些文件或目录。
在上面的第一个例子中,我们查找所有文件和一个目录(./backup)。使用 -type
参数以及一个单字母类型来限制搜索。使用 'f' 表示普通文件,使用 'd' 查找目录,使用 'l' 查找符号链接。参考手册页,获得 find
的其他可能类型。清单 20 展示了只搜索目录的结果(-type d
)和文件名(*,在本例中可为任何内容)搜索结果。
[ian@echidna lpi103-2]$ find . -type d . ./backup [ian@echidna lpi103-2]$ find . -type d -name "*" . ./backup
注意,-type d
不包含任何形式的名称指定,将显示在其名称中具有一个前导圆点的目录(在本例中只包括当前目录),和通配符 “*” 的作用相同。
我们还可以按照文件大小进行搜索,可以搜索具有指定大小的文件 (n),或者搜索文件大小大于 (+n) 或小于 (-n) 某个给定值的文件。通过使用上限和下限大小,我们可以查找大小在某个给定范围内的文件。默认情况下,find
的 -size
选项假设包含 512 字节的块为一个单位,用 'b' 表示。此外,指定 'c' 表示字节,或指定 'k' 表示千字节。在清单 21 中,我们首先查找大小为 0 的所有文件,然后查找大小为 24 或 25 字节的所有文件。注意,指定 -empty
而不是 -size 0
也将查找空文件。
[ian@echidna lpi103-2]$ find . -size 0 ./f1a ./f6 ./f8 ./f2 ./f3 ./f7 ./f4 ./f9 ./f5 [ian@echidna lpi103-2]$ find . -size -26c -size +23c -print ./text2 ./text5 ./backup/text1.bkp.1 ./backup/text1.bkp.2 ./text1
清单 21 中的第二个例子引入了 -print
选项,它演示了一个可能会对搜索返回的结果执行的操作。在 bash shell 中,如果没有指定任何操作的话,那么这将是默认操作。在某些系统和 shell 中,需要指定一个操作;否则,不会生成输出。
其他操作包括 -ls
(输出文件信息,与 ls -lids
命令的输出差不多)和 -exec
(为每个文件执行一个命令)。-exec
必须以分号终止,必须对分号进行转义,以避免 shell 首先解释分号。如果希望在命令中使用返回的文件,还必须指定 {}。记住,花括号对于 shell 也是有意义的,因此必须进行转义(或引用)。清单 22 展示了如何使用 -ls
和 -exec
选项列出文件信息。注意第二个表单没有列出 inode 信息。
[ian@echidna lpi103-2]$ find . -size -26c -size +23c -ls 933893 4 -rw-rw-r-- 1 ian ian 25 Aug 11 14:27 ./text2 933900 4 -rw-rw-r-- 1 ian ian 24 Aug 11 18:47 ./text5 934193 4 -rw-rw-r-- 1 ian ian 24 Aug 12 15:36 ./backup/text1.bkp.1 934195 4 -rw-rw-r-- 1 ian ian 24 Aug 12 15:36 ./backup/text1.bkp.2 933892 4 -rw-rw-r-- 1 ian ian 24 Aug 11 14:02 ./text1 [ian@echidna lpi103-2]$ find . -size -26c -size +23c -exec ls -l '{}' \; -rw-rw-r--. 1 ian ian 25 2009-08-11 14:27 ./text2 -rw-rw-r--. 1 ian ian 24 2009-08-11 18:47 ./text5 -rw-rw-r--. 1 ian ian 24 2009-08-12 15:36 ./backup/text1.bkp.1 -rw-rw-r--. 1 ian ian 24 2009-08-12 15:36 ./backup/text1.bkp.2 -rw-rw-r--. 1 ian ian 24 2009-08-11 14:02 ./text1
-exec
选项可用于您能够想象到的所有用途。例如:find . -empty -exec rm '{}' \;
删除目录树中的所有空文件 find . -name "*.htm" -exec mv '{}' '{}l' \;
将所有 .htm 文件重命名为 .html 文件。
在最后一个 find
例子中,我们使用由 touch
命令描述的时间戳来查找具有特定时间戳的文件。清单 23 给出了三个例子:
当用于 -mtime -2
时,find
命令将查找在最近两天以内修改的所有文件。在本例中,一天即指与当前日期和时间相关的 24 个小时。注意,如果您希望根据访问时间而不是修改时间查找文件,那么将使用 -atime
。
添加 -daystart
选项意味着我们希望使用日历计算天数,从午夜开始。现在,f3 已被排除在列表以外。
最后,我们将展示如何使用以分钟计算的时间范围而不是天数来查找在过去的 1 个小时(60 分钟)至 10 个小时(600 分钟)之间发生修改的文件。
[ian@echidna lpi103-2]$ date Sat Aug 15 00:27:36 EDT 2009 [ian@echidna lpi103-2]$ find . -mtime -2 -type f -exec ls -l '{}' \; -rw-rw-r--. 1 ian ian 0 2009-08-14 18:25 ./f1a -rw-rw-r--. 1 ian ian 4 2009-08-14 18:25 ./f1 -rw-rw-r--. 1 ian ian 0 2009-08-13 06:00 ./f6 -rw-rw-r--. 1 ian ian 0 2009-08-15 02:00 ./f8 -rw-rw-r--. 1 ian ian 0 2009-08-14 18:27 ./f2 -rw-rw-r--. 1 ian ian 58 2009-08-14 17:30 ./text10 -rw-rw-r--. 1 ian ian 0 2009-08-14 11:00 ./f4 -rw-rw-r--. 1 ian ian 0 2009-11-05 00:00 ./f9 [ian@echidna lpi103-2]$ find . -daystart -mtime -2 -type f -exec ls -l '{}' \; -rw-rw-r--. 1 ian ian 0 2009-08-14 18:25 ./f1a -rw-rw-r--. 1 ian ian 4 2009-08-14 18:25 ./f1 -rw-rw-r--. 1 ian ian 0 2009-08-15 02:00 ./f8 -rw-rw-r--. 1 ian ian 0 2009-08-14 18:27 ./f2 -rw-rw-r--. 1 ian ian 58 2009-08-14 17:30 ./text10 -rw-rw-r--. 1 ian ian 0 2009-08-14 11:00 ./f4 -rw-rw-r--. 1 ian ian 0 2009-11-05 00:00 ./f9 [ian@echidna lpi103-2]$ find . -mmin -600 -mmin +60 -type f -exec ls -l '{}' \; -rw-rw-r--. 1 ian ian 0 2009-08-14 18:25 ./f1a -rw-rw-r--. 1 ian ian 4 2009-08-14 18:25 ./f1 -rw-rw-r--. 1 ian ian 0 2009-08-14 18:27 ./f2 -rw-rw-r--. 1 ian ian 58 2009-08-14 17:30 ./text10
find
命令的手册页可以帮助您了解各种选项,我们无法在这篇简短的介绍中一一介绍它们。
回页首
文件名通常具有一个后缀,比如 gif、jpeg 或 html,它将告诉您文件中可能包含的内容。Linux 不需要这种后缀,因此通常不会使用它们来识别文件类型。了解正在处理的文件的类型将使您知道程序将使用什么工具显示或操作文件。file
命令将使您了解到一个或多个文件中的数据的类型。清单 24 展示了使用 file
命令的一些例子。
[ian@echidna lpi103-2]$ file backup text1 f2 ../p-ishields.jpg /bin/echo backup: directory text1: ASCII text f2: empty ../p-ishields.jpg: JPEG image data, JFIF standard 1.02 /bin/echo: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.18, stripped
file
命令尝试使用三种测试来对每个文件进行分类。比如,文件系统测试使用 stat
命令的结果来判断某个文件或目录是否为空。名为 magic的测试将检查文件中的特定内容,这些内容可以识别文件。这些签名也被称为魔术数字(magic number)。最后,语言测试将查看文本文件中的内容,尝试确定某个文件是 XML 文件、C 或 C++ 语言源文件、troff 文件,或是其他被认为是某些语言处理器的源文件。找到的第一种类型将被生成报告,除非 -k
或 --keep-going
选项被指定。
file
命令具有许多选项,您可以通过手册页获得详细介绍。清单 25 展示了如何使用 -i
(或 --mime
)选项来将文件类型显示为 MIME 字符串,而不是普通的人类可读输出。
[ian@echidna lpi103-2]$ file -i backup text1 f2 ../p-ishields.jpg /bin/echo backup: application/x-directory; charset=binary text1: text/plain; charset=us-ascii f2: application/x-empty; charset=binary ../p-ishields.jpg: image/jpeg; charset=binary /bin/echo: application/x-executable; charset=binary
魔术数字文件也由 file
命令管理。请在此查看手册页获得更多信息。
注意:作为 ImageMagick 包的一部分,identify
命令可以用作额外一种工具,为识别图像文件类型提供更多细节。
回页首
当您备份、归档或传输文件时,通常会对文件进行压缩。在 Linux 环境中,两个流行的压缩程序为 gzip
和 bzip2
。gzip
命令使用 Lempel-Ziv 算法,而 bzip2
使用 Burrows-Wheeler 块分类算法。
压缩通常对文本文件比较有效。许多图像格式的文件已经进行了数据压缩,因此对这些或其他二进制文件进行压缩效果不大。为了演示对较大文本文件执行的压缩,让我们将 /etc/services 复制到我们一直使用的目录中,并使用 gzip 对它执行压缩,如清单 26 所示。我们使用 cp
的 -p
选项保留 /etc/services 的时间戳。注意,压缩后的文件具有相同的时间戳,并且具有一个 .gz 后缀。
[ian@echidna lpi103-2]$ cp -p /etc/services [ian@echidna lpi103-2]$ ls -l serv* -rw-r--r--. 1 ian ian 630983 2009-04-10 04:42 services [ian@echidna lpi103-2]$ gzip services [ian@echidna lpi103-2]$ ls -l serv* -rw-r--r--. 1 ian ian 124460 2009-04-10 04:42 services.gz
您使用 gzip
的 -d
选项解压缩使用 gzip 压缩过的文件,更常见的是使用 gunzip
命令。清单 27 展示了第一种方法。注意,未压缩的文件现在具有原始名和时间戳。
[ian@echidna lpi103-2]$ gzip -d services.gz [ian@echidna lpi103-2]$ ls -l serv* -rw-r--r--. 1 ian ian 630983 2009-04-10 04:42 services
bzip2
命令以与 gzip
类似的方式运行,如清单 28 所示。
[ian@echidna lpi103-2]$ ls -l serv* -rw-r--r--. 1 ian ian 630983 2009-04-10 04:42 services [ian@echidna lpi103-2]$ bzip2 services [ian@echidna lpi103-2]$ ls -l serv* -rw-r--r--. 1 ian ian 113444 2009-04-10 04:42 services.bz2 [ian@echidna lpi103-2]$ bunzip2 services.bz2 [ian@echidna lpi103-2]$ ls -l serv* -rw-r--r--. 1 ian ian 630983 2009-04-10 04:42 services
根据设计,bzip2
的许多选项与 gzip
的选项是相似的,但是这两个命令不包含完全相同的选项。您可能已经注意到,在我们的两个例子中,未压缩的文件具有与原始文件相同的文件名和时间戳。然而,重命名或 touch 已压缩文件会改变这一行为。gzip
命令的 -N
或 --name
选项会强制保留名称和时间戳,但是 bzip2
不会。gzip
命令还有一个 -l
选项,用于显示与已压缩文件有关的信息,包括将在解压缩时使用的名称。清单 29 解释了这两个命令之间的一些区别。
[ian@echidna ~]$ ls -l serv* -rw-r--r--. 1 ian ian 630983 2009-04-10 04:42 services [ian@echidna ~]$ gzip -N services [ian@echidna ~]$ touch services.gz [ian@echidna ~]$ mv services.gz services-x.gz [ian@echidna ~]$ ls -l serv* -rw-r--r--. 1 ian ian 124460 2009-09-23 14:08 services-x.gz [ian@echidna ~]$ gzip -l services-x.gz compressed uncompressed ratio uncompressed_name 124460 630983 80.3% services-x [ian@echidna ~]$ gzip -lN services-x.gz compressed uncompressed ratio uncompressed_name 124460 630983 80.3% services [ian@echidna ~]$ gunzip -N services-x.gz [ian@echidna ~]$ ls -l serv* -rw-r--r--. 1 ian ian 630983 2009-04-10 04:42 services [ian@echidna ~]$ [ian@echidna ~]$ bzip2 services [ian@echidna ~]$ mv services.bz2 services-x.bz2 [ian@echidna ~]$ touch services-x.bz2 [ian@echidna ~]$ ls -l serv* -rw-r--r--. 1 ian ian 113444 2009-09-23 14:10 services-x.bz2 [ian@echidna ~]$ bunzip2 services-x.bz2 [ian@echidna ~]$ ls -l serv* -rw-rw-r--. 1 ian ian 630983 2009-09-23 14:10 services-x [ian@echidna ~]$ rm services-x # Don't need this any more
gzip
和 bzip2
都接受来自 stdin 的输入。两者都支持用 -c
选项将输出导出到 stdout。
bzip2
还有另外两个相关的命令。
bzcat
命令将文件解压缩到 stdout,其作用等同于 bzip2 -dc
。
bzip2recover
命令尝试从受损害的 bzip2 文件中恢复数据。
手册页将帮助您了解 gzip
和 bzip2
的其他选项。
另外两个更旧一点的程序是 compress
和 uncompress
,它们仍然频繁出现在 Linux 和 UNIX 系统中。
此外,来自 Info-ZIP 项目的 zip
和 unzip
命令也在 Linux 中得到了实现。它们提供了跨平台的压缩功能,可以广泛应用于各种硬件和操作系统。注意,并不是所有操作系统都支持相同的文件属性或文件系统功能。如果您下载用 zip 压缩过的产品文件并在 Windows 系统上解压缩它,然后将结果文件传输到 CD 或 DVD 中以用于 Linux 安装,您可能会遇到安装问题,原因在于,例如,Windows 系统不支持原始的未压缩文件集所含的符号链接。
有关这些或其他压缩程序的更多信息,请参考相关的手册页。
回页首
tar
、cpio
和 dd
命令被常用于备份文件组甚至是整个分区,目的是归档文件或传输到另外一个用户或站点。LPIC-2 认证中的考试 201 关注更加详细的备份事项。
有三种常用的备份方法:
差异 或累积 备份是指对自上一次完全备份之后发生更改的所有内容进行备份。要执行恢复,需要最近一次的完全备份和最新的差异备份。
增量 备份是指只对自上一次增量备份后发生变化的内容执行备份。要执行恢复,需要最近一次的完全备份以及这次完全备份之后的所有增量备份(按顺序)。
完全 备份是指一次完整的备份,通常为整个文件系统、目录或相关文件组。这种备份所需的时间是三种备份中最长的,因此通常与其他两种方法的其中一种结合使用。
这些命令以及本文中学习的其他命令为您提供了执行任何这些备份任务的工具。
tar
(最初来自 Tape ARchive)从一组输入文件或目录中创建一个归档文件,即 tarfile 或 tarball;它还从此类归档中恢复文件。如果某个目录被作为输入提供给 tar
,所有文件和子目录都被自动包括,这使得 tar
可以非常方便地归档您的目录结构的子树。
输出可以被导入到文件、磁带或软盘之类的设备或是 stdout 中。输出位置使用 -f
选项指定。其他常见选项为:-c
用于创建归档,-x
用于提取归档,-v
用于详细输出,它将列出被处理的文件,-z
用于使用 gzip 压缩,而 -j
用于使用 bzip2 压缩。大部分 tar
选项包含使用一个连字符的简单格式和使用一对连字符的详细格式。这里解释了简单格式。参考手册页,获得有关详细格式和额外选项的内容。
清单 30 展示了如何使用 tar
创建 lpi103-2 目录的备份。
[ian@echidna lpi103-2]$ tar -cvf ../lpitar1.tar . ./ ./text3 ./yab ... ./f5
您通常希望压缩归档文件来节省空间或减少传输时间。tar
命令的 GNU 版本允许您使用一个单个选项实现此目的 ―-z
表示使用 gzip
压缩,而 -b
表示使用 bzip2
压缩。清单 31 演示了 -z
选项的使用,以及两种归档文件在大小方面的差异。
[ian@echidna lpi103-2]$ tar -zcvf ../lpitar2.tar ~/lpi103-2/ tar: Removing leading `/' from member names /home/ian/lpi103-2/ /home/ian/lpi103-2/text3 /home/ian/lpi103-2/yab ... /home/ian/lpi103-2/f5 [ian@echidna lpi103-2]$ ls -l ../lpitar* -rw-rw-r--. 1 ian ian 30720 2009-09-24 15:38 ../lpitar1.tar -rw-rw-r--. 1 ian ian 881 2009-09-24 15:39 ../lpitar2.tar
清单 31 还显示了 tar
的另外一个重要特性。我们使用了一个绝对目录路径,而输出的第一行告诉我们 tar
正在从成员名称中删除前导斜线 (/)。这允许将文件恢复到其他位置以进行检验,如果您尝试恢复系统文件的话,这一点尤其重要。如果您确实需要存储绝对名称,那么使用 -p
选项。在创建归档时,避免将绝对路径名和相对路径名混在一起始终是一种好的想法,因为在从归档恢复时,所有名称都将为相对名称。
tar
命令可以使用 -r
或 --append
选项将额外的文件附加到归档中。这会造成归档中出现文件的多个副本。在这种情况下,最后 一个文件将在恢复操作期间被恢复。您可以使用 --occurrence
选项从多个文件中选择一个特定文件。如果归档位于常规文件系统而非磁带中,那么可以使用 -u
或 --update
选项来更新一个归档。这种工作方式类似于附加到一个归档,区别在于,归档中的文件的时间戳将与文件系统中的时间戳进行比较,并且只有在归档版本之后发生修改的文件被附加。如前所述,这不适用于磁带归档。
tar
命令也可以将归档与当前文件系统加以比较,并恢复来自归档的文件。使用 -d
、--compare
或 --diff
选项执行比较。输出将显示内容有差异的文件,以及时间戳不同的文件。一般情况下,将只列出不同的文件(如果有的话)。使用前面讨论的 -v
选项获得详细输出。-C
或 -- directory
选项将告诉 tar
从指定的目录开始执行操作,而不是从当前目录开始。
清单 32 展示了一些例子。我们使用 touch
来修改 f1 文件的时间戳,然后演示了 tar
的比较操作,之后从其中一个归档中恢复 f1。我们将使用各种操作来进行说明。
[ian@echidna lpi103-2]$ touch f1 [ian@echidna lpi103-2]$ tar --diff --file ../lpitar1.tar . ./f1: Mod time differs [ian@echidna lpi103-2]$ tar -df ../lpitar2.tar -C / home/ian/lpi103-2/f1: Mod time differs [ian@echidna lpi103-2]$ tar -xvf ../lpitar1.tar ./f1 # See below ./f1 [ian@echidna lpi103-2]$ tar --compare -f ../lpitar2.tar --directory /
您为恢复指定的文件或目录必须匹配归档中的名称。在本例中,如果尝试只恢复 f1 而不是 ./f1,那么将是无效的。您可以使用 globbing,但是需要注意不要恢复过多或过少的内容。如果您不确定归档内容的话,您可以使用 --list
或 -t
选项来列出归档内容。清单 33 展示了一个通配符说明示例,它将恢复更多的文件,而不仅仅是 ./f1。
[ian@echidna lpi103-2]$ tar -tf ../lpitar1.tar "*f1*" ./f1a ./f1
可以使用 find
命令选择要归档的文件,然后将结果传递给 tar。我们将在讨论 cpio
时探讨这种方法,但是同样的方法也可以用于 tar
。
和本文介绍的其他命令一样,这篇简要的介绍无法涵盖所有的选项。请参考手册页或信息页了解更多内容。
cpio
命令在 copy-out 模式下创建归档,在 copy-in 模式下恢复归档,或在 copy-pass 模式下将一组文件从一个位置复制到另一个位置。您将对 copy-out 模式使用 -o
或 --create
选项,对 copy-in 模式使用 -i
或 --extract
选项,而对 copy-pass 模式使用 -p
或 --pass-through
选项。输入是在 stdin 中提供的一组文件。输出被指向 stdout,或者是由 -f
或 --file
选项指定的设备或文件。
清单 34 展示了如何使用 find
命令生成一组文件,并将列表传递给 cpio
。注意,对 find
使用了 -print0
选项来为文件名生成 null-terminate 字符串,而 cpio
上的对应的 --null
选项将读取这个格式。这将正确地处理包含内嵌空格或换行符的文件名。-depth
选项告诉 find
在目录名的前面列出目录条目。在本例中,我们仅仅创建了 lpi103-2 目录的两个归档,一个使用相对名称,一个使用绝对名称。我们没有使用 find
的众多功能对所选文件进行限制,比如只查找在本周修改过的文件。
[ian@echidna lpi103-2]$ find . -depth -print0 | cpio --null -o > ../lpicpio.1 3 blocks [ian@echidna lpi103-2]$ find ~/lpi103-2/ -depth -print0 | cpio --null -o > ../lpicpio.2 4 blocks
如果您希望按照归档顺序列出文件,那么对 cpio
添加 -v
选项。
copy-in 模式下的 cpio
命令(选项 -i
或 --extract
)可以列出归档的内容或恢复所选文件。当您列出文件时,指定 --absolute-filenames
选项将减少无关消息的数量,较旧版本的 cpio
在从包含前导 / 字符的每个路径中分离该字符时会发出这些消息。该选项在许多最新实现中都被忽略。选择性列出前面的归档的输出如清单 35 所示。
[ian@echidna lpi103-2]$ cpio -i --list "*backup*" < ../lpicpio.1 backup backup/text1.bkp.1 backup/text1.bkp.2 3 blocks [ian@echidna lpi103-2]$ cpio -i --list absolute-filenames "*text1*" < ../lpicpio.2/home/ian/lpi103-2/text10 /home/ian/lpi103-2/backup/text1.bkp.1 /home/ian/lpi103-2/backup/text1.bkp.2 /home/ian/lpi103-2/text1 4 blocks
清单 36 展示了如何将路径中含有 “text1” 的所有文件恢复到一个临时子目录中。其中一些文件位于子目录中。与 tar
不同,如果目录树不存在的话,您将需要明确地指定 -d
或 --make-directories
选项。此外,cpio
不会使用归档副本替换文件系统中任何较新的文件,除非您指定了-u
或 --unconditional
选项。
[ian@echidna lpi103-2]$ mkdir temp [ian@echidna lpi103-2]$ cd temp [ian@echidna temp]$ cpio -idv "*f1*" "*.bkp.1" < ../../lpicpio.1 f1a f1 backup/text1.bkp.1 3 blocks [ian@echidna temp]$ cpio -idv "*.bkp.1" < ../../lpicpio.1 cpio: backup/text1.bkp.1 not created: newer or same age version exists backup/text1.bkp.1 3 blocks [ian@echidna temp]$ cpio -id --no-absolute-filenames "*text1*" < ../../lpicpio.2cpio: Removing leading `/' from member names 4 blocks ./home/ian/lpi103-2/backup/text1.bkp.1 ./home/ian/lpi103-2/backup/text1.bkp.2 ./home/ian/lpi103-2/text1 ./backup/text1.bkp.1 [ian@echidna temp]$ cd .. [ian@echidna lpi103-2]$ rm -rf temp # You may remove these after you have finished
有关其他选项的更多细节,请参考手册页。
就其最简单形式而言,dd
命令将一个输入文件复制到一个输出文件。您已经了解过 cp
命令,因此您可能希望知道为什么还要用另外一个命令复制文件。dd
命令可以完成很多常规 cp
命令无法办到的事情。特别是,它可以对文件执行转换,比如将小写转换为大写,或将 ASCII 转换为 EBCDIC。它还可以重新阻塞(reblock)一个文件,当将文件传输给磁带时可能需要这样做。它还可以跳过或只包括所选的文件块。最后,它可以读取和写入原始设备,比如 /dev/sda,这允许您创建和恢复作为完整分区映像的文件。写入到设备通常需要根权限。
我们将首先来看一个使用 conv
将文件转换为大写的简单例子,如清单 37 所示。我们使用 if
选项指定输入文件,而不是使用默认的 stdin。类似的 of
选项可用于覆盖 stdout 默认输出。为了演示的目的,我们使用 ibs
和 obs
选项指定了不同的输入和输出块大小。对于较大的文件,在进行磁盘之间的传输时,使用较大的块大小加速操作会比较方便。另外,块大小最常用于磁带。注意,清单末尾的三行状态代码表示有多少完整的和局部的块被读取和写入,以及被传输的数据的总量。
[ian@echidna lpi103-2]$ cat text6 1 apple 2 pear 3 banana 9 plum 3 banana 10 apple 1 apple 2 pear 3 banana 9 plum 3 banana 10 apple [ian@echidna lpi103-2]$ dd if=text6 conv=ucase ibs=20 obs=30 1 APPLE 2 PEAR 3 BANANA 9 PLUM 3 BANANA 10 APPLE 1 APPLE 2 PEAR 3 BANANA 9 PLUM 3 BANANA 10 APPLE 4+1 records in 3+1 records out 98 bytes (98 B) copied, 0.00210768 s, 46.5 kB/s
任何文件都可能是一个原始设备。这种情况通常出现在磁带中,但是一个完整的磁盘分区,比如 /dev/hda1 或 /dev/sda2,可以被备份到一个文件或磁带中。理想情况下,设备上的文件系统应当被解除挂载,或至少为只读挂载,从而确保数据在备份期间不会发生修改。清单 39 展示了一个示例,其中输入文件是一个原始设备 dev/sda3,而输出文件是位于根用户的主目录中的文件 backup-1。要将文件转储到磁带或软盘中,将进行 of=/dev/fd0
或 of=/dev/st0
等指定。
[root@echidna ~]# dd if=/dev/sda2 of=backup-1 1558305+0 records in 1558305+0 records out 797852160 bytes (798 MB) copied, 24.471 s, 32.6 MB/s
注意,797,852,160 字节的数据被复制,而输出文件也包含这么多的数据,即使实际上只会使用 3% 的分区。除非您使用硬件压缩将文件复制到磁盘,否则您将希望对数据进行压缩。清单 39 展示了实现此目的的一种方法,以及 ls
和 df
命令的输出,向您展示了文件的大小和 /dev/sda3 上的文件系统的使用百分比。
[root@echidna ~]# dd if=/dev/sda2 |gzip >backup-2 1558305+0 records in 1558305+0 records out 797852160 bytes (798 MB) copied, 23.4617 s, 34.0 MB/s [root@echidna ~]# ls -l backup-[12] -rw-r--r--. 1 root root 797852160 2009-09-25 17:13 backup-1 -rw-r--r--. 1 root root 995223 2009-09-25 17:14 backup-2 [root@echidna ~]# df -h /dev/sda2 Filesystem Size Used Avail Use% Mounted on /dev/sda2 755M 18M 700M 3% /grubfile
gzip 压缩将文件大小减小到未压缩大小的 20%。然而,未使用的块可能包含任何数据,因此即使压缩过的备份也可能要比分区的总数据大。
如果按照处理的记录的数量对总字节进行划分,您将看到 dd
将写入多个包含 512 字节的数据块。当复制到磁带之类的原始输出设备中时,这将导致产生非常低效的操作。如前所述,指定 obs
选项来改变输出的大小,或用 ibs
选项来指定输入块大小。您还可以仅指定 bs
来将输入和输出块大小同时指定为一个常用值。在使用磁带时,记住使用相同的块大小来读取和写入磁带。
如果需要多个磁带或其他可移动存储来保存备份,那么需要使用 split
之类的工具将它们分为更小的部分。如果需要跳过磁盘或磁带标签之类的块,可以使用 dd
完成。参见手册页中的示例。
dd
命令无法被文件系统感知,因此需要恢复一个分区的转储才能知道分区的内容。清单 40 展示了如何将清单 39 中转储的文件恢复到分区 /dev/sdc,该分区创建在可移动 USB 驱动上,专门用于这个用途。
[root@echidna ~]# gunzip backup-2 -c | dd of=/dev/sdc7 1558305+0 records in 1558305+0 records out 797852160 bytes (798 MB) copied, 30.624 s, 26.1 MB/s
您可能对一些使用 dd
命令在幕后执行实际的设备写入工作的 CD 和 DVD 刻录应用程序感兴趣。如果您使用的工具提供了大量实际使用的命令,并且您现在对 dd
有了更多的了解,那么您会发现查看日志会大有裨益。实际上,如果您将一个 ISO 映像刻录到一张 CD 或 DVD 磁盘,一种确定没有错误的方法就是使用 dd
回读磁盘并通过 cmp
工具传递结果。清单 41 使用我们在本文中创建的备份文件解释了这一常见技巧,而不是使用 ISO 映像。注意,我们使用映像的文件大小计算读取的块的数量。
[root@echidna ~]# ls -l backup-1 -rw-r--r--. 1 root root 797852160 2009-09-25 17:13 backup-1 [root@echidna ~]# echo $(( 797852160 / 512 )) # calculate number of 512 byte blocks 1558305 [root@echidna ~]# dd if=/dev/sdc7 bs=512 count=1558305 | cmp - backup-1 1558305+0 records in 1558305+0 records out 797852160 bytes (798 MB) copied, 26.7942 s, 29.8 MB/s