tar命令可以归档文件。它最初是设计用来将数据存储在磁带上,因此其名字也来源于Tape ARchive。tar可以将多个文件和文件夹打包为单个文件,同时还能保留所有的文件属性,如所有者、权限等。由tar创建的文件通常称为tarball。在这则攻略里,我们将学习如何使用tar创建归档文件。
7.2.1 预备知识
所有类Unix操作系统中都默认包含tar命令。它语法简单,文件格式具备可移植性。tar支持多种选项,可用于调整命令的行为。
7.2.2 实战演练
用 tar 创建归档文件
$ tar -cf output.tar [SOURCES]
[root@dev workspace]# ls vitesthost.txt man_db.conf test.sh[root@dev workspace]# tar -cf vitest.tar vitest/*[root@dev workspace]# lsecho file.txt input.txt out.txt sample2.txt tools vitestelse golang out.html printf.sh showArgs.sh umq vitest.tarfile2 if.sh output.txt sample1.txt temp.txt variables.sh welcome.txt
选项-c表示创建新的归档文件。选项-f表示归档文件名,该选项后面必须跟一个文件名称:
$ tar -cf archive.tar file1 file2 file3 folder1 ..
显示归档文件中所包含的文件
选项-t可以列出归档文件中所包含的文件
$ tar -tf vitest.tarvitest/host.txtvitest/man_db.confvitest/test.sh
[root@dev workspace]# tar -tf vitest.tarvitest/host.txtvitest/man_db.confvitest/test.sh[root@dev workspace]#
显示归档文件更多信息
选项-v或-vv参数可以在命令输出中加入更多的细节信息。这个特性叫作“冗长模式(v,verbose)”或“非常冗长模式(vv,very verbose)”。对于能够在终端中生成报告的命令,-v是一个约定的选项。该选项能够显示出更多的细节,例如文件权限、所有者所属的分组、文件修改日期等信息:
$ tar -tvf vitest.tar-rw-r--r-- root/root 453 2022-01-18 21:54 vitest/host.txt-rw-r--r-- root/root 5166 2022-01-17 23:08 vitest/man_db.conf-rw-r--r-- root/root 11 2022-01-18 22:29 vitest/test.sh

文件名必须紧跟在
-f之后出现,而且-f应该是选项中的最后一个。假如你希望使用冗长模式,应该像这样写:$ tar -cvf output.tar file1 file2 file3 folder1 ..
7.2.3 工作原理
tar命令可以接受一组文件名或是通配符(如*.txt),以此指定需要进行归档的源文件。命令执行完毕后,所有的源文件都会被归入指定的归档文件中。
命令行参数有数量限制,我们无法一次性传递数百个文件或目录。如果要归档的文件很多,那么使用追加选项(详见下文)要更安全些。
7.2.4 补充内容
让我们再来看看tar命令的其他特性。
向归档文件中追加文件
选项-r可以将新文件追加到已有的归档文件末尾:
$ tar -rvf original.tar new_file
创建一个包含文本文件的归档:
$ echo hello >hello.txt$ tar -cf archive.tar hello.txt$ tar -tvf archive.tar-rw-r--r-- root/root 6 2022-01-24 21:31 hello.txt


选项-t可以列出归档文件中的内容。选项-f可以指定归档文件名:
$ tar -tvf archive.tar-rw-r--r-- root/root 6 2022-01-24 21:31 hello.txt
接着使用选项-r向该归档文件中再追加一个文件:
$ echo world >world.txt$ tar -rf archive.tar world.txt$ tar -tf archive.tarhello.txtworld.txt

这个归档文件中现在包含了两个文件。
从归档文件中提取文件或目录
选项-x可以将归档文件的内容提取到当前目录:
$ tar -xf archive.tar

使用-x时,tar命令将归档文件中的内容提取到当前目录。我们也可以用选项-C来指定将文件提取到哪个目录:
$ tar -xf archive.tar -C /path/to/extraction_directory
该命令将归档文件的内容提取到指定目录中。它提取的是归档文件中的全部内容。我们可以通过将文件名作为命令行参数来提取特定的文件:
$ tar -xvf archive.tar hello.txt

上面的命令只提取hello.txt,忽略其他文件。
在 tar 中使用 stdin 和 stdout
在归档时,我们可以将stdout指定为输出文件,这样另一个命令就可以通过管道来读取(作为stdin)并进行其他处理。
当通过安全shell(Secure Shell,SSH)传输数据时,这招很管用。例如:
$ tar cvf - files/ | ssh user@example.com "tar xv -C Documents/"
在上面的例子中,对files目录中的内容进行了归档并将其输出到stdout(由-指明),然后提取到远程系统中的Documents目录中。
拼接两个归档文件
我们可以用选项-A合并多个tar文件。
假设我们现在有两个tar文件:file1.tar和file2.tar。下面的命令可以将file2.tar的内容合并到file1.tar中:
$ tar -Af file1.tar file2.tar
查看内容,验证操作是否成功:
$ tar -tvf file1.tar
通过检查时间戳来更新归档文件中的内容
追加选项(-r)可以将指定的任意文件加入到归档文件中。如果同名文件已经存在,那么归档文件中就会包含两个名字一样的文件。我们可以用更新选项-u指明:只添加比归档文件中的同名文件更新(newer)的文件。
$ tar -tf archive.tarfileafilebfilec
仅当filea自上次被加入archive.tar后出现了改动才对其执行追加操作:
$ tar -uf archive.tar filea
如果两个filea的时间戳相同,则什么都不会发生。
使用touch命令修改文件的时间戳,然后再用tar命令:
$ tar -uvvf archive.tar filea-rw-r--r-- slynux/slynux 0 2010-08-14 17:53 filea
因为时间戳比归档文件中的同名文件更新,因此执行追加操作。可以用选项
$ tar -tf archive.tar-rw-r--r-- slynux/slynux 0 2010-08-14 17:52 filearw-r--r-- slynux/slynux 0 2010-08-14 17:52 fileb-rw-r--r-- slynux/slynux 0 2010-08-14 17:52 filec-rw-r--r-- slynux/slynux 0 2010-08-14 17:53 filea
如你所见,一个新的filea被加入到了归档文件中。当从中提取文件时,tar会挑选最新的filea。
比较归档文件与文件系统中的内容
选项-d可以将归档中的文件与文件系统中的文件作比较。这个功能能够用来确定是否需要创建新的归档文件。
$ tar -df archive.tarafile: Mod time differsafile: Size differs
从归档中删除文件
我们可以用--delete选项从归档中删除文件:
$ tar -f archive.tar --delete file1 file2 ..
或者
$ tar --delete --file archive.tar [FILE LIST]
$ tar -vf archive.tar --delete hello.txt

来看另外一个例子:
$ tar -tf archive.tarfileafilebfilec$ tar --delete --file archive.tar filea$ tar -tf archive.tarfilebfilec
压缩 tar 归档文件
tar命令默认只归档文件,并不对其进行压缩。不过tar支持用于压缩的相关选项。压缩能够显著减少文件的体积。归档文件通常被压缩成下列格式之一。
- gzip格式:
file.tar.gz或file.tgz。 - bzip2格式:
file.tar.bz2。 - Lempel-Ziv-Markov格式:
file.tar.lzma。
不同的tar选项可以用来指定不同的压缩格式:
-j指定bunzip2格式;-z指定gzip格式;--lzma指定lzma格式。
不明确指定上面那些特定的选项也可以使用压缩功能。tar能够基于输出或输入文件的扩展名来进行压缩。为了让为了让tar支持根据扩展名自动选择压缩算法,使用-a或--auto-compress选项:
$ tar -acvf archive.tar.gz filea fileb filecfileafilebfilec
[root@dev workspace]# lsarchive.tar file2 if.sh output.txt sample1.txt temp.txt variables.sh welcome.txtecho file.txt input.txt out.txt sample2.txt tools vitestelse golang out.html printf.sh showArgs.sh umq vitest.tar[root@dev workspace]# echo filea>filea[root@dev workspace]# echo fileb>fileb[root@dev workspace]# echo filec>filec[root@dev workspace]# rm -f archive.tar[root@dev workspace]# lsecho filea file.txt input.txt out.txt sample2.txt tools vitestelse fileb golang out.html printf.sh showArgs.sh umq vitest.tarfile2 filec if.sh output.txt sample1.txt temp.txt variables.sh welcome.txt[root@dev workspace]# tar -acvf archive.tar.gz filea fileb filecfileafilebfilec[root@dev workspace]# lsarchive.tar.gz file2 filec if.sh output.txt sample1.txt temp.txt variables.sh welcome.txtecho filea file.txt input.txt out.txt sample2.txt tools vitestelse fileb golang out.html printf.sh showArgs.sh umq vitest.tar[root@dev workspace]# tar -tf archive.tar.gzfileafilebfilec[root@dev workspace]#
在归档过程中排除部分文件
选项--exclude [PATTERN]可以将匹配通配符模式的文件排除在归档过程之外。
例如,排除所有的.txt文件:
$ tar -cf arch.tar * --exclude "*.txt"
注意,模式应该使用双引号来引用,避免
shell对其进行扩展。
也可以将需要排除的文件列表放入文件中,同时配合选项-X:
$ cat listfileafileb$ tar -cf arch.tar * -X list
这样就把filea和fileb排除了。
排除版本控制目录
tar文件的用处之一是用来分发源代码。很多源代码都是使用版本控制系统进行维护的,如subversion、Git、mercurial、CVS(参考上一章)。版本控制系统中的代码目录通常包含一些特殊目录,如.svn或.git。这些目录由版本控制系统负责管理,对于开发者之外的用户并没有什么用。因此无需将其包含在分发给用户的tar文件内。
tar的选项--exclude-vcs可以在归档时排除版本控制相关的文件和目录。例如:
$ tar --exclude-vcs -czvvf source_code.tar.gz eye_of_gnome_svn
打印总字节数
选项-totals可以打印出归档的总字节数。注意,这是实际数据的字节数。如果使用了压缩选项,文件大小会小于总的归档字节数:
$ tar -cf arc.tar * --exclude "*.txt" --totalsTotal bytes written: 20480 (20KiB, 12MiB/s)
7.2.5 参考
7.4 节会讲解gzip命令。
