tar命令可以归档文件。它最初是设计用来将数据存储在磁带上,因此其名字也来源于Tape ARchivetar可以将多个文件和文件夹打包为单个文件,同时还能保留所有的文件属性,如所有者、权限等。由tar创建的文件通常称为tarball。在这则攻略里,我们将学习如何使用tar创建归档文件。

7.2.1 预备知识

所有类Unix操作系统中都默认包含tar命令。它语法简单,文件格式具备可移植性。tar支持多种选项,可用于调整命令的行为。

7.2.2 实战演练

tar命令可以创建、更新、检查以及解包归档文件。

用 tar 创建归档文件

  1. $ tar -cf output.tar [SOURCES]
  1. [root@dev workspace]# ls vitest
  2. host.txt man_db.conf test.sh
  3. [root@dev workspace]# tar -cf vitest.tar vitest/*
  4. [root@dev workspace]# ls
  5. echo file.txt input.txt out.txt sample2.txt tools vitest
  6. else golang out.html printf.sh showArgs.sh umq vitest.tar
  7. file2 if.sh output.txt sample1.txt temp.txt variables.sh welcome.txt

选项-c表示创建新的归档文件。选项-f表示归档文件名,该选项后面必须跟一个文件名称:

  1. $ tar -cf archive.tar file1 file2 file3 folder1 ..

image.png

显示归档文件中所包含的文件

选项-t可以列出归档文件中所包含的文件

  1. $ tar -tf vitest.tar
  2. vitest/host.txt
  3. vitest/man_db.conf
  4. vitest/test.sh
  1. [root@dev workspace]# tar -tf vitest.tar
  2. vitest/host.txt
  3. vitest/man_db.conf
  4. vitest/test.sh
  5. [root@dev workspace]#

显示归档文件更多信息

选项-v-vv参数可以在命令输出中加入更多的细节信息。这个特性叫作“冗长模式(vverbose)”或“非常冗长模式(vvvery verbose)”。对于能够在终端中生成报告的命令,-v是一个约定的选项。该选项能够显示出更多的细节,例如文件权限、所有者所属的分组、文件修改日期等信息:

  1. $ tar -tvf vitest.tar
  2. -rw-r--r-- root/root 453 2022-01-18 21:54 vitest/host.txt
  3. -rw-r--r-- root/root 5166 2022-01-17 23:08 vitest/man_db.conf
  4. -rw-r--r-- root/root 11 2022-01-18 22:29 vitest/test.sh

image.png

文件名必须紧跟在-f之后出现,而且-f应该是选项中的最后一个。假如你希望使用冗长模式,应该像这样写: $ tar -cvf output.tar file1 file2 file3 folder1 ..

7.2.3 工作原理

tar命令可以接受一组文件名或是通配符(如*.txt),以此指定需要进行归档的源文件。命令执行完毕后,所有的源文件都会被归入指定的归档文件中。

命令行参数有数量限制,我们无法一次性传递数百个文件或目录。如果要归档的文件很多,那么使用追加选项(详见下文)要更安全些。

7.2.4 补充内容

让我们再来看看tar命令的其他特性。

向归档文件中追加文件

选项-r可以将新文件追加到已有的归档文件末尾:

  1. $ tar -rvf original.tar new_file

创建一个包含文本文件的归档:

  1. $ echo hello >hello.txt
  2. $ tar -cf archive.tar hello.txt
  3. $ tar -tvf archive.tar
  4. -rw-r--r-- root/root 6 2022-01-24 21:31 hello.txt

image.png
image.png
选项-t可以列出归档文件中的内容。选项-f可以指定归档文件名:

  1. $ tar -tvf archive.tar
  2. -rw-r--r-- root/root 6 2022-01-24 21:31 hello.txt

接着使用选项-r向该归档文件中再追加一个文件:

  1. $ echo world >world.txt
  2. $ tar -rf archive.tar world.txt
  3. $ tar -tf archive.tar
  4. hello.txt
  5. world.txt

image.png
这个归档文件中现在包含了两个文件。

从归档文件中提取文件或目录

选项-x可以将归档文件的内容提取到当前目录:

  1. $ tar -xf archive.tar

image.png
使用-x时,tar命令将归档文件中的内容提取到当前目录。我们也可以用选项-C来指定将文件提取到哪个目录:

  1. $ tar -xf archive.tar -C /path/to/extraction_directory

该命令将归档文件的内容提取到指定目录中。它提取的是归档文件中的全部内容。我们可以通过将文件名作为命令行参数来提取特定的文件:

  1. $ tar -xvf archive.tar hello.txt

image.png
上面的命令只提取hello.txt,忽略其他文件。

在 tar 中使用 stdin 和 stdout

在归档时,我们可以将stdout指定为输出文件,这样另一个命令就可以通过管道来读取(作为stdin)并进行其他处理。

当通过安全shellSecure ShellSSH)传输数据时,这招很管用。例如:

  1. $ tar cvf - files/ | ssh user@example.com "tar xv -C Documents/"

在上面的例子中,对files目录中的内容进行了归档并将其输出到stdout(由-指明),然后提取到远程系统中的Documents目录中。

拼接两个归档文件

我们可以用选项-A合并多个tar文件。

假设我们现在有两个tar文件:file1.tarfile2.tar。下面的命令可以将file2.tar的内容合并到file1.tar中:

  1. $ tar -Af file1.tar file2.tar

查看内容,验证操作是否成功:

  1. $ tar -tvf file1.tar

通过检查时间戳来更新归档文件中的内容

追加选项(-r)可以将指定的任意文件加入到归档文件中。如果同名文件已经存在,那么归档文件中就会包含两个名字一样的文件。我们可以用更新选项-u指明:只添加比归档文件中的同名文件更新(newer)的文件。

  1. $ tar -tf archive.tar
  2. filea
  3. fileb
  4. filec

仅当filea自上次被加入archive.tar后出现了改动才对其执行追加操作:

  1. $ tar -uf archive.tar filea

如果两个filea的时间戳相同,则什么都不会发生。

使用touch命令修改文件的时间戳,然后再用tar命令:

  1. $ tar -uvvf archive.tar filea
  2. -rw-r--r-- slynux/slynux 0 2010-08-14 17:53 filea

因为时间戳比归档文件中的同名文件更新,因此执行追加操作。可以用选项

  1. $ tar -tf archive.tar
  2. -rw-r--r-- slynux/slynux 0 2010-08-14 17:52 filea
  3. rw-r--r-- slynux/slynux 0 2010-08-14 17:52 fileb
  4. -rw-r--r-- slynux/slynux 0 2010-08-14 17:52 filec
  5. -rw-r--r-- slynux/slynux 0 2010-08-14 17:53 filea

如你所见,一个新的filea被加入到了归档文件中。当从中提取文件时,tar会挑选最新的filea

比较归档文件与文件系统中的内容

选项-d可以将归档中的文件与文件系统中的文件作比较。这个功能能够用来确定是否需要创建新的归档文件。

  1. $ tar -df archive.tar
  2. afile: Mod time differs
  3. afile: Size differs

从归档中删除文件

我们可以用--delete选项从归档中删除文件:

  1. $ tar -f archive.tar --delete file1 file2 ..

或者

  1. $ tar --delete --file archive.tar [FILE LIST]
  1. $ tar -vf archive.tar --delete hello.txt

image.png
来看另外一个例子:

  1. $ tar -tf archive.tar
  2. filea
  3. fileb
  4. filec
  5. $ tar --delete --file archive.tar filea
  6. $ tar -tf archive.tar
  7. fileb
  8. filec

压缩 tar 归档文件

tar命令默认只归档文件,并不对其进行压缩。不过tar支持用于压缩的相关选项。压缩能够显著减少文件的体积。归档文件通常被压缩成下列格式之一。

  • gzip格式:file.tar.gzfile.tgz
  • bzip2格式:file.tar.bz2
  • Lempel-Ziv-Markov格式:file.tar.lzma

不同的tar选项可以用来指定不同的压缩格式:

  • -j指定bunzip2格式;
  • -z指定gzip格式;
  • --lzma指定lzma格式。

不明确指定上面那些特定的选项也可以使用压缩功能。tar能够基于输出或输入文件的扩展名来进行压缩。为了让为了让tar支持根据扩展名自动选择压缩算法,使用-a--auto-compress选项:

  1. $ tar -acvf archive.tar.gz filea fileb filec
  2. filea
  3. fileb
  4. filec
  1. [root@dev workspace]# ls
  2. archive.tar file2 if.sh output.txt sample1.txt temp.txt variables.sh welcome.txt
  3. echo file.txt input.txt out.txt sample2.txt tools vitest
  4. else golang out.html printf.sh showArgs.sh umq vitest.tar
  5. [root@dev workspace]# echo filea>filea
  6. [root@dev workspace]# echo fileb>fileb
  7. [root@dev workspace]# echo filec>filec
  8. [root@dev workspace]# rm -f archive.tar
  9. [root@dev workspace]# ls
  10. echo filea file.txt input.txt out.txt sample2.txt tools vitest
  11. else fileb golang out.html printf.sh showArgs.sh umq vitest.tar
  12. file2 filec if.sh output.txt sample1.txt temp.txt variables.sh welcome.txt
  13. [root@dev workspace]# tar -acvf archive.tar.gz filea fileb filec
  14. filea
  15. fileb
  16. filec
  17. [root@dev workspace]# ls
  18. archive.tar.gz file2 filec if.sh output.txt sample1.txt temp.txt variables.sh welcome.txt
  19. echo filea file.txt input.txt out.txt sample2.txt tools vitest
  20. else fileb golang out.html printf.sh showArgs.sh umq vitest.tar
  21. [root@dev workspace]# tar -tf archive.tar.gz
  22. filea
  23. fileb
  24. filec
  25. [root@dev workspace]#

image.png

在归档过程中排除部分文件

选项--exclude [PATTERN]可以将匹配通配符模式的文件排除在归档过程之外。

例如,排除所有的.txt文件:

  1. $ tar -cf arch.tar * --exclude "*.txt"

注意,模式应该使用双引号来引用,避免shell对其进行扩展。

也可以将需要排除的文件列表放入文件中,同时配合选项-X

  1. $ cat list
  2. filea
  3. fileb
  4. $ tar -cf arch.tar * -X list

这样就把fileafileb排除了。

排除版本控制目录

tar文件的用处之一是用来分发源代码。很多源代码都是使用版本控制系统进行维护的,如subversionGitmercurialCVS(参考上一章)。版本控制系统中的代码目录通常包含一些特殊目录,如.svn.git。这些目录由版本控制系统负责管理,对于开发者之外的用户并没有什么用。因此无需将其包含在分发给用户的tar文件内。

tar的选项--exclude-vcs可以在归档时排除版本控制相关的文件和目录。例如:

  1. $ tar --exclude-vcs -czvvf source_code.tar.gz eye_of_gnome_svn

打印总字节数

选项-totals可以打印出归档的总字节数。注意,这是实际数据的字节数。如果使用了压缩选项,文件大小会小于总的归档字节数:

  1. $ tar -cf arc.tar * --exclude "*.txt" --totals
  2. Total bytes written: 20480 (20KiB, 12MiB/s)

7.2.5 参考

7.4 节会讲解gzip命令。