Contents

Linux中tar命令简介

1. 概述

当我们想要在不同的 Linux 系统之间传输多个文件时,将它们打包成一个存档通常是个好主意。

如果我们考虑归档和通用文件打包,磁带归档 ( *tar)*是大多数 Linux 系统上的事实标准。

在本快速教程中,我们将学习如何使用tar 实用程序来操作此类存档。

2. 语法

我们先来看看基本语法:

$ tar {operation} [options...] [file]...

默认情况下,我们至少需要指定一个操作。默认选项和输入取决于操作类型。我们将分别介绍这些内容。

在 Linux 中,一切皆文件。这意味着我们还可以归档文件的目录结构。

由于历史原因,** tar接受各种格式的操作**:

  • 以破折号开头的 UNIX 短格式
  • GNU 长格式,前面有两个破折号
  • 不使用破折号的旧样式格式

我们的大多数示例都使用 UNIX 风格的格式。但是,我们还需要一些 GNU 选项。

3. 基本操作

大多数时候,我们只需要三个基本操作

  • 创建存档
  • 提取存档
  • 列出档案

让我们仔细看看每一个。

3.1. 创建档案

让我们使用*-c*标志创建一个由两个文件组成的存档

$ tar -c -f archive.tar file1 file2
$ ls
archive.tar  file1  file2

在此示例中,我们还使用*-f*选项定义了输出存档文件

如果我们不指定输出文件,则默认行为是使用 TAPE环境变量中定义的内容或已编译的默认值。

在大多数情况下,它会尝试使用标准输出流。这将产生一个错误,除非我们将输出 重定向到一个文件:

$ tar -c file1 file2 > archive.tar
$ ls
archive.tar  file1  file2

现在让我们假设我们有两个文件在一个名为test的文件夹中:

$ ls -alh test
-rw-r--r-- 1 user users    6 Mar 20 23:19 file1
-rw-r--r-- 1 user users   12 Mar 20 23:19 file2
$ tar -c -f folder.tar test
$ ls -allh
-rw-r--r-- 1 user users  10K Mar 20 23:19 folder.tar
drwxr-xr-x 2 user users 4.0K Mar 20 23:19 test

默认情况下,tar递归地归档文件夹。因此,存档还将包含父目录和两个文件。

3.2. 提取档案

现在我们已经了解了如何创建存档,让我们来看看如何提取存档。

我们可以使用*-x标志指示tar*提取存档

$ tar -x -f archive.tar
$ ls -allh
-rw-r--r-- 1 user users  10K Mar 20 22:51 archive.tar
-rw-r--r-- 1 user users    6 Mar 18 20:54 file1
-rw-r--r-- 1 user users   12 Mar 18 20:54 file2

默认行为是覆盖具有相同名称的现有文件系统文件。

请注意,我们再次使用*-f*选项来指定要提取的存档。

同样,我们可以通过将存档重定向到tar的标准输入流来省略它:

$ tar -x < archive.tar

这给了我们相同的结果。

我们还可以只提取存档的特定成员

$ tar -x -f archive.tar file2
$ ls -allh
-rw-r--r-- 1 user users  10K Mar 20 22:51 archive.tar
-rw-r--r-- 1 user users   12 Mar 18 20:54 file2

这里有一个潜在的问题。还记得我们在上一节中归档文件夹吗?

在这种情况下,我们需要指定文件的完全限定名称

$ tar -x -f folder.tar test/file2
$ ls -allh
-rw-r--r-- 1 user users  10K Mar 20 23:30 folder.tar
drwxr-xr-x 2 user users 4.0K Mar 20 23:31 test
$ ls -allh test
-rw-r--r-- 1 user users   12 Mar 20 23:19 file2

结果也有点出乎意料。注意,我们还将test文件夹提取到放置file2 的位置。

3.3. 上市档案

有时我们不想提取存档,而只是看一下它的内容。这就是列表选项的用途。

我们可以再次结合使用*-t选项和-f*来打印存档的内容

$ tar -t -f archive.tar 
file1
file2

同样,我们也可以使用重定向

$ tar -t < archive.tar
file1
file2

现在让我们看一下前面示例中的folder存档:

$ tar -t -f folder.tar
test/
test/file1
test/file2

同样,我们也可以指定列出哪些文件或文件夹

$ tar -t -f folder.tar test/file1
test/file1

4.高级操作

现在让我们看一下更高级的示例。

4.1. 更新档案

在某些情况下,我们希望将新文件添加到现有存档中。

幸运的是,我们可以使用带有-u选项的tar**。还记得我们的第一个存档有两个文件吗?

现在让我们添加第三个:

$ tar -t -f archive.tar 
file1
file2
$ tar -u -f archive.tar file3
$ tar -t -f archive.tar
file1
file2
file3

我们还可以用更新的版本更新现有的存档成员。如果tar为我们的文件检测到更新的修改日期,它会将其添加到存档中。

我们修改file3的内容,重新添加:

$ tar -u -f archive.tar file3
$ tar -t -f archive.tar
file1
file2
file3
file3

这里发生了什么?现在我们的存档中有两个file3实例。

更新不会替换存档中的现有文件。相反,新修改的文件被添加到我们的档案中。

那么更新是如何工作的呢?当我们提取档案时,提取的顺序由我们归档的顺序给出。

这意味着 file3的第一个实例首先被提取,然后被file3的第二个(更新的)版本覆盖。

现在让我们尝试再次添加相同的文件而不修改它:

$ tar -u -f archive.tar file3
$ tar -t -f archive.tar
file1
file2
file3
file3

没有添加任何内容,因为tar根据修改日期检测到我们的文件没有更改。

4.2. 附加到档案

我们还可以使用*-r*选项附加到现有存档

说到这里,我们可能会问 update 和 append 有什么区别。

与更新不同,当我们追加时,tar不关心修改日期

现在让我们尝试追加而不是更新我们之前示例中使用的相同file3

$ tar -r -f archive.tar file3
$ tar -t -f archive.tar 
file1
file2
file3
file3
file3

请注意,我们现在在存档中拥有同一文件的三个副本。让我们解释一下我们是如何结束这种情况的。

第一个实例是我们在第一次更新存档时添加的实例。 第二个是我们修改过的,然后用它再次更新存档。 第三个实例与第二个实例相同,我们只是将其附加到我们的存档中。请记住,更新是不可能的。

4.3. 串联档案

当我们想将现有档案合并为一个时,连接就派上用场了。

假设我们有包含测试文件的archive1.tararchive2.tar

$ tar -t -f archive1.tar 
file1
file2
$ tar -t -f archive2.tar 
file3

我们可以使用-A*标志*合并第一个存档中的所有内容:

$ tar -A -f archive1.tar archive2.tar
$ tar -t -f archive1.tar 
file1
file2
file3

4.4. 从档案中删除成员

最后,在某些情况下,我们希望从存档中删除文件或文件夹

让我们在前面的示例中使用此操作:

$ tar --delete -f archive1.tar file2
$ tar -t -f archive1.tar 
file1
file3

请注意,与以前的选项不同,我们现在使用 GNU 长格式。那是因为我们没有一个简短的等价物。

最重要的是,我们在使用它时应该小心,因为它涉及重写整个存档,这可能是一个缓慢的过程

5. 选项

到目前为止,我们已经看到了一些基本选项。当然,根据操作类型的不同,我们还可以使用更多

现在让我们玩一些最有趣的。

5.1. 压缩和解压

到目前为止,我们的档案只是一种对文件进行分组的方式。

让我们使用*-z*选项添加一些gzip 压缩

$ tar -c -z -f compressed.tar.gz large1 large2
$ ls -allh
-rw-r--r-- 1 user users  31K Mar 18 23:38 compressed.tar.gz
-rw-r--r-- 1 user users  10M Mar 18 22:16 large1
-rw-r--r-- 1 user users  20M Mar 18 22:19 large2
-rw-r--r-- 1 user users  31M Mar 18 23:38 uncompressed.tar.gz

当然,大小的差异是惊人的,因为我们使用了一些虚拟文件。

像往常一样,我们总是可以查看tar手册以了解所有可能的压缩算法

提取压缩档案怎么样?我们像常规存档一样进行操作:

$ tar -x -f compressed.tar.gz
$ ls -allh
-rw-r--r-- 1 user users  31K Mar 20 23:34 compressed.tar.gz
-rw-r--r-- 1 user users  10M Mar 18 22:16 large1
-rw-r--r-- 1 user users  20M Mar 18 22:19 large2

tar命令在存档中使用一个特殊的元数据字节来描述压缩算法。

因此,我们不需要指定相应的解压选项

不幸的是,缺点是我们无法以任何方式修改压缩档案

5.2. *.tgz和*.tar.gz文件扩展名

我们已经了解到可以使用tar命令的*-z选项来压缩 tarball。通常,我们会使用.tar.gz*扩展名来命名存档文件。但是,有时我们可以看到一些 *.tgz文件。

** .tgz和*.tar.gz扩展名都告诉我们文件是gzip压缩的 tarball。可以使用相同的tar*命令提取它们。因此,这两个扩展之间没有区别。**

我们可能会问,好吧,如果这两个扩展意味着同样的事情,为什么我们有两个扩展?让我们简单地解释一下。

如果我们回顾过去的DOS ,我们会注意到FAT 文件系统只支持8.3 文件名 方案。即在老版本的DOS和Windows系统中无法识别名为foo.tar.gz的文件。因此,我们有一个较短的文件扩展名“ tgz ”来表示双扩展名“ tar.gz ”,以便在 FAT 文件系统中识别gzip压缩的 tarball。

今天,所有现代文件系统都支持双文件扩展名。因此,我们通常将“ tar.gz ”作为 gzip压缩包的扩展名,以获得更详细的信息。

同样,对于*bzip2 *压缩的 tarball,我们有“ tar.bz2 ”扩展名。

5.3. 冗长

我们可以使用*-v*选项为所有操作启用更详细的输出

让我们看一下压缩档案:

$ tar -t -v -f compressed.tar.gz 
-rw-r--r-- user/users 10485760 2020-03-18 22:16 large1
-rw-r--r-- user/users 20971520 2020-03-18 22:19 large2

这为我们提供了有关存档内容的更多详细信息。

让我们回到我们的更新示例:

$ tar -t -v -f archive.tar 
-rw-r--r-- user/users   10240 2020-03-21 18:55 file1
-rw-r--r-- user/users      12 2020-03-18 20:54 file2
-rw-r--r-- user/users      40 2020-03-22 19:46 file3
-rw-r--r-- user/users      48 2020-03-22 22:18 file3

我们现在可以看到文件的修改日期和大小。

当我们在存档中有文件夹时,此选项通常会派上用场。

5.4. 多卷档案

在便携式磁盘容量有限的时代,我们习惯于将档案分成多个卷。

我们可以指示tar最大Nx1024字节的卷分块我们的存档,甚至指定自定义大小。

让我们创建一个最大卷大小为 8 MB 的多卷存档:

$ tar -c -M -L 8M -f archive1.tar large1 large2
Prepare volume #2 for ‘archive1.tar’ and hit return: n archive2.tar
Prepare volume #3 for ‘archive2.tar’ and hit return: n archive3.tar
Prepare volume #4 for ‘archive3.tar’ and hit return: n archive4.tar
$ ls -allh
-rw-r--r-- 1 user users 8.1M Mar 18 23:07 archive1.tar
-rw-r--r-- 1 user users 8.1M Mar 18 23:07 archive2.tar
-rw-r--r-- 1 user users 8.1M Mar 18 23:07 archive3.tar
-rw-r--r-- 1 user users 6.0M Mar 18 23:07 archive4.tar
-rw-r--r-- 1 user users  10M Mar 18 22:16 large1
-rw-r--r-- 1 user users  20M Mar 18 22:19 large2

我们使用**-M标志来指示我们想要一个多卷存档,然后我们使用*-L*选项指定卷大小**。

结果,tar以交互方式提示我们命名每个卷。我们通过指定 n 选项和相应的名称来实现。

这里要记住的一个重要方面是我们不能压缩多卷档案

5.5. 文件选择

当我们对大量文件进行操作时,大多数时候,我们想要一种更有效的方式来包含或排除单个文件。

幸运的是,我们可以使用-T*选项从基于文件的列表中指定我们的输入*。

我们先来看看我们的文件列表:

$ cat input-files 
file1
file2
file3
folder/file4

我们只需要确保将文件放在不同的行上。

现在让我们创建一个存档并查看其中的内容:

$ tar -c -f archive.tar -T input-files
$ tar -t -f archive.tar
file1
file2
file3
folder/file4

我们还可以在提取存档时使用列表选项