Skip to content

打包与压缩

字数: 6167 字 时长: 23 分钟

在 Linux 系统中,打包和压缩是两个常见的操作,它们通常一起使用,以便于文件的传输、存储和备份。

打包

在 Linux 系统中,打包也被称作「归档」(Archiving)。归档是将多个文件和目录整合成一个单一的归档文件的过程,这极大地方便了数据的组织和存储。归档文件的一个显著优势在于,它们能够保留原始的目录结构和文件属性,确保在解压时能够精确地恢复文件的原始布局。例如,在进行数据备份时,归档可以将相关文件和目录紧凑地封装在一起,便于存储和管理。由于目录结构和文件属性得以保留,在需要恢复数据时,可以更准确地还原到其原始状态。归档文件的这种形式不仅提高了数据管理的效率,也使得无论是本地存储还是数据传输都变得更加有序和高效。

压缩

归档文件和压缩文件都允许将多个文件和目录集合成一个单一的文件,但它们的处理方式有所不同:

  • 归档文件保持了文件的原始大小,而压缩文件则通过特殊的存储技术减小了文件所占用的磁盘空间。
  • 压缩技术的核心在于利用算法减少文件体积,同时保留尽可能多的原始信息。这个过程通常涉及到识别文件中的重复数据,并用一个简短的代码来代替这些重复的数据,从而实现文件体积的缩减。

压缩是利用特定算法对文件进行处理,目的是在保留尽可能多的文件信息的同时,让文件的体积变小。其基本原理是查找文件内的重复字节,然后建立一个相同字节的词典文件,并用一个特定的代码来表示这些重复的内容。例如,在一个待压缩的文件中,如果有多处出现「Linux」这样的字符串,在压缩过程中,这个词就会用一个代码表示并写入词典文件,从而实现缩小文件体积的效果。

由于计算机处理的信息是以二进制形式呈现的,所以压缩软件会把二进制信息中相同的字符串用特殊字符标记,通过合理的数学计算,能够极大地压缩文件的体积。将一个或者多个文件用压缩软件进行压缩后,就会形成一个文件压缩包,这样既可以节省存储空间,又方便在网络上进行传送。

如果理解了文件压缩的基本原理,就很容易想到,对文件进行压缩有可能会损坏文件中的内容。因此,压缩可以分为有损压缩和无损压缩。无损压缩比较容易理解,即压缩后的数据必须准确无误,在解压缩后能够完全还原到原始状态。有损压缩则是指即使丢失个别的数据,对文件也不会造成太大的影响。有损压缩广泛应用于动画、声音和图像文件中,比如影碟文件格式 mpeg、音乐文件格式 mp3 以及图像文件格式 jpg 等都是典型代表。

使用压缩工具对文件进行压缩后生成的文件被称为压缩包,通常情况下,压缩包的体积只有原文件的一半甚至更小。需要注意的是,压缩包中的数据无法直接使用,在使用之前需要利用压缩工具将文件数据还原,这个过程又称为解压缩。

gzip 命令

gzip 是一个在 Unix 和类 Unix 系统(包括 Linux)中广泛使用的文件压缩程序,它属于 GNU 项目的一部分。gzip 代表 GNU zip,它使用 DEFLATE 压缩算法来压缩文件数据,这是一种 Lempel-Ziv 编码(LZ77)的变种,特别适用于压缩文本文件。

在 Linux 系统中,gzip 是一个被频繁使用的命令,主要用于文件的压缩与解压缩,其既便捷又实用。gzip 不但能够对较大且较少使用的文件进行压缩,从而节省磁盘空间,还能与 tar 命令相结合,共同构成 Linux 操作系统中较为流行的压缩文件格式。据统计,gzip 命令对文本文件的压缩率可达 60% 至 70%。减少文件大小具有两个显著好处:

  1. 能够减少存储空间的占用。
  2. 在通过网络传输文件时,可以缩短传输时间。

gzip 的一些关键特性:

  • 压缩比:gzip 通常对文本文件提供较好的压缩比,但对已经压缩过的文件(如 JPEG 图片、MP3 音频)则效果不大。
  • 压缩级别:gzip 允许用户选择不同的压缩级别,从 1(最快压缩速度,最低压缩比)到 9(最慢压缩速度,最高压缩比)。默认级别是 6。
  • 扩展名:gzip 压缩的文件通常使用 .gz 作为文件扩展名。
  • 命令行工具:gzip 是一个命令行工具,可以通过命令行参数来控制其行为。
  • 保留原文件:gzip 在压缩文件时,默认不会删除原始文件,除非使用 -f(强制)选项。
  • 递归操作:gzip 可以递归地压缩目录中的所有文件。
  • 查看压缩文件内容:使用 zcatzgrep 可以查看 .gz 文件的内容,而无需解压。
shell
gzip [OPTION]... [FILE]...
常见选项作用
-k在使用 gzip 对文件进行压缩时,默认行为是压缩完成后删除原始文件,只留下压缩后的文件。如果使用该选项,gzip 会在压缩后保留原始文件,即原始文件和压缩文件都会保留在文件系统中。
-c这个选项用于将输出写到标准输出,并且保留原始文件。它的主要作用是可以将压缩后的内容输出到其他地方,比如重定向到另一个文件或者通过管道传递给其他命令。
-d用于解压缩文件。当有一个 .gz 格式的压缩文件,想要恢复原始文件时可以使用这个选项。
-r用于递归地处理目录下的所有文件和子目录。例如当要压缩一个目录下的所有文件,这个选项非常有用。
-l用于列出压缩文件的相关信息,如压缩文件的大小、未压缩文件的大小、压缩比等。
-[1-9]用于指定压缩比,数字范围是 1 - 9。1 表示最快的压缩速度,但压缩比最低;9 表示最慢的压缩速度,但压缩比最高。默认情况下是 6。
参数作用
FILE指要压缩的一个或多个文件的名称。可以指定单个文件,也可以使用通配符来指定多个文件。如果 FILE 参数被省略,gzip 会尝试从标准输入(stdin)读取数据进行压缩。

当使用 gzip 命令且不加特殊参数来压缩一个文件时(例如 gzip file.txt),gzip 会读取 file.txt 的内容,通过压缩算法(如 DEFLATE)进行压缩,然后将原始的 file.txt 文件替换为压缩后的 file.txt.gz 文件。从效果上看,原始文件好像被「删除」了,但实际上它被新的压缩文件所替代。

这是因为 gzip 的设计目的之一是节省磁盘空间,通过这种替换方式可以直接利用原始文件的存储空间来存放压缩后的文件。例如,如果原始文件是一个占用大量磁盘空间的大型文本文件,压缩后生成的 .gz 文件体积会显著减小,从而更有效地利用磁盘资源。

gzip 本身并不具备将多个文件组合成一个归档文件的功能。例如,如果有文件 file1.txt、file2.txt 和 file3.txt,gzip 不能直接把它们打包成一个归档文件,而像 tar 这样的工具才可以实现归档操作。因为 gzip 命令本身设计用于压缩单个文件,并不直接支持压缩整个目录。

示例:

  1. 基本压缩

    gzip 压缩命令非常简单,甚至不需要指定压缩之后的压缩包名,只需指定源文件名即可:

    shell
    [root@localhost ~]# echo "hello,gzip" > text.log
    [root@localhost ~]# gzip text.log

    需要注意,在使用 gzip 命令时,默认情况下,原始文件会被替换,也就是说,压缩后,原始文件 text.log 会被压缩文件 text.log.gz 替换。

    shell
    [root@localhost ~]# ls
    text.log.gz
  2. 保留源文件压缩

    在使用 gzip 命令压缩文件时,默认行为是压缩完成后删除原始文件,只留下压缩后的文件。如果想要保留源文件可以使用 -k 选项:

    shell
    [root@localhost ~]# echo "hello,gzip" > text1.log
    [root@localhost ~]# gzip -k text1.log 
    [root@localhost ~]# ls
    text.log.gz  text1.log  text1.log.gz

    除此之外,还可以使用 -c 选项,它用于将压缩数据输出到标准输出(stdout),而不是直接写入文件。这允许将压缩结果重定向到文件或管道传输给其他命令:

    shell
    [root@localhost ~]# echo "hello,gzip" > text2.log
    [root@localhost ~]# gzip -c text2.log > text2.log.gz
    [root@localhost ~]# ls
    text.log.gz  text1.log  text1.log.gz  text2.log  text2.log.gz

    这个命令会压缩 text2.log,并将压缩数据输出到标准输出,然后通过重定向操作符 > 将输出保存到 text2.log.gz 文件中。

  3. 压缩目录

    gzip 命令并不具备直接压缩目录及其子文件的功能。如果尝试对一个目录使用 gzip 命令,会收到一个错误消息,因为 gzip 只能对单个文件进行操作。

    shell
    [root@localhost ~]# gzip /root
    gzip: /root is a directory -- ignored

    如果希望对目录下所有文件(包括子目录中的文件)进行压缩,需要使用 -r 选项,这样它就会递归地对目录及其子目录中的所有文件逐个进行压缩:

    shell
    [root@localhost ~]# gzip -r /root
    gzip: /root/text1.log.gz already exists; do you wish to overwrite (y or n)? y
    gzip: /root/text2.log.gz already exists; do you wish to overwrite (y or n)? y
    [root@localhost ~]# ls
    text.log.gz  text1.log.gz  text2.log.gz

gunzip 命令

gunzip 是一个用于解压缩文件的命令,主要用于处理由 gzip 压缩的文件。在 Linux 和 Unix 系统中,它是一个常用的工具。其功能是将以 .gz 为后缀的压缩文件恢复为原始的未压缩文件格式。gunzipgzip 实际上是一个程序的不同调用方式,gunzip 等价于 gzip -d

shell
gzip [OPTION]... [FILE]...
常见选项作用
-c用于将解压缩后的内容输出到标准输出,而不是直接生成解压缩后的文件。这在需要将解压缩后的内容重定向到其他位置或者通过管传递给其他命令时非常有用。
-f强制解压缩文件。如果目标文件已经存在,使用这个选项可以强制覆盖已有的文件。不过在使用此选项时需要谨慎,因为它可能会导致已有数据丢失。
-k解压缩后保留原始的压缩文件。默认情况下,gunzip 会删除原始的 .gz 文件
-l用于列出压缩文件中的相关信息,如压缩文件的大小、未压缩文件的大小、压缩比等信息。
-r用于递归地解压缩包含多个 .gz 文件的目录。它会查找所有 .gz 文件并将它们解压缩。
-t用于测试压缩文件的完整性,检查是否有损坏,而不实际解压缩文件。
参数作用
FILE指要压缩的一个或多个文件的名称。可以指定单个文件,也可以使用通配符来指定多个文件。

示例:

  1. 直接解压缩文件

    shell
    [root@localhost ~]# gunzip text.log.gz 
    [root@localhost ~]# ls
    text.log  text1.log.gz  text2.log.gz

    还可以使用 gzip -d 命令,同样也可以解压文件:

    shell
    [root@localhost ~]# ls
    text.log  text1.log  text2.log.gz

    如果想保留源文件,可以使用 -k 选项:

    shell
    [root@localhost ~]# gzip -dk text2.log.gz 
    [root@localhost ~]# ls
    text.log  text1.log  text2.log  text2.log.gz
  2. 解压缩目录下的内容

    shell
    [root@localhost ~]# gzip -dkr  /root/
    gzip: /root/text2.log already exists; do you wish to overwrite (y or n)? y
    [root@localhost ~]# ls
    text.log  text1.log  text2.log  text2.log.gz

    如果压缩的是一个纯文本文件,则可以直接使用 zcat 命令在不解压缩的情况下查看这个文本文件中的内容。例如:

    shell
    [root@localhost ~]# zcat text2.log.gz 
    hello,gzip

bzip2 命令

bzip2 是一个用于文件压缩和解压缩的命令行工具。它使用了 Burrows - Wheeler 块排序文本压缩算法和霍夫曼编码,能够有效地减小文件的大小,节省存储空间并方便文件传输。这种压缩算法在处理文本文件和其他一些数据文件时表现出色。

在 Rocky Linux 最小安装下默认是没有安装 bzip2 命令的,可以通过 dnf 进行安装:

shell
[root@localhost ~]# dnf -y install bzip2

与 gzip 相比,bzip2 通常可以提供更高的压缩率,但压缩和解压缩的速度稍慢,尤其适合文本文件和其他可以容忍少量压缩和解压缩时间的数据。

shell
bzip2 [OPTION]... [FILE]...
常见选项作用
-k在压缩或解压缩文件后保留原始文件。
-d用于解压缩 .bz2 格式的文件。
-k解压缩后保留原始的压缩文件。默认情况下,gunzip 会删除原始的 .gz 文件
-z强制进行压缩操作。这个选项实际上是默认选项,一般很少需要显式使用,因为在没有指定 -d 选项时,bzip2 会自动进行压缩。
-t检查 .bz2 文件的完整性。它会读取压缩文件并验证其是否能够正确解压缩,而不会实际解压缩文件内容。
-c将压缩或解压缩的结果输出到标准输出(通常是终端屏幕),而不是生成一个文件。这个选项在需要将结果重定向到其他地方(如另一个文件或管道)时非常有用。
-1 .. -9指定压缩比。-1 是最快的压缩,压缩率最低;-9 是最慢的压缩,压缩率最高。默认是 -9。
参数作用
FILE指是一个或多个 .bz2 扩展名的压缩文件。

示例:

  1. 压缩多个文件并保留原始文件

    shell
    [root@localhost ~]# bzip2 -k file1.txt file2.txt file3.txt
    [root@localhost ~]# ll
    total 24
    -rw-r--r--. 1 root root 12 Dec  5 09:56 file1.txt
    -rw-r--r--. 1 root root 55 Dec  5 09:56 file1.txt.bz2
    -rw-r--r--. 1 root root 12 Dec  5 09:56 file2.txt
    -rw-r--r--. 1 root root 55 Dec  5 09:56 file2.txt.bz2
    -rw-r--r--. 1 root root 12 Dec  5 09:56 file3.txt
    -rw-r--r--. 1 root root 55 Dec  5 09:56 file3.txt.bz2

    这个命令会压缩 file1.txt、file2.txt 和 file3.txt,并保留这些原始文件。

  2. 压缩文件并指定压缩级别

    shell
    [root@localhost ~]# bzip2 -9 -k file1.txt

    这个命令会以最高压缩级别(-9)压缩 file1.txt 并保留原始文件。

  3. 测试多个压缩文件的完整性

    shell
    [root@localhost ~]# bzip2 -tv file1.txt.bz2 file2.txt.bz2 file3.txt.bz2 
    file1.txt.bz2: ok
    file2.txt.bz2: ok
    file3.txt.bz2: ok

这里,-t 指定要进行模拟解压,不实际生成结果,也就是说类似检查文件,当然就算目录下面有 file1.txt 也不会有什么错误输出了,因为它根本不会真的解压文件。为了在屏幕上输出,这里加上 -v 选项了。

bunzip2 命令

bunzip2 是一个用于解压缩 .bz2 格式文件的命令行工具。它是 bzip2 压缩工具的配套程序,主要作用是将通过 bzip2 压缩后的文件恢复到原始状态。

shell
bzip2 [OPTION]... [FILE]...
常见选项作用
-k解压缩文件后保留原始的 .bz2 格式文件。件。
-f强制解压缩。如果目标文件已经存在,或者文件有一些特殊的权限设置等可能导致解压缩失败的情况,使用 -f 选项可以尝试强制进行解压缩操作。不过需要注意的是,这种强制操作可能会覆盖已有的文件内容,所以要谨慎使用。
-s在压缩、解压缩及检查时减少内存用量。这意味着任何文件都可以在较少的内存中进行解压缩,尽管速度可能会减半。
参数作用
FILE指是一个或多个 .bz2 扩展名的压缩文件。

示例:

  1. 解压文件

    shell
    root@localhost ~]# bunzip2 file1.txt.bz2

    这会将 file1.txt.bz2 解压为 file.txt,并且删除原始的 .bz2 文件。

  2. 保留原文件解压文件

    shell
    root@localhost ~]# bunzip2 -k file2.txt.bz2

tar 命令

tar 是一个在 Unix 和类 Unix 系统(包括 Linux)中广泛使用的归档工具,用于打包(归档)和解包文件。

NOTE

最小化安装时,tar 命令默认时没有安装的,可以使用 dnf 命令进行安装。例如:dnf -y install tar

shell
tar [OPTION...] [FILE]...
常见选项作用
-c用于生成一个新的归档文件,将指定的文件和目录打包进去。在创建归档时,tar 不会对文件进行压缩,只是将它们合并到一个文件中。如果归档文件名已存在,tar 会覆盖它,除非使用了 -P 选项来保留原文件。
-x用于将归档文件中的内容解压到当前目录或指定目录。如果归档文件被压缩,tar 会自动检测压缩方法并解压。如果归档文件包含多个文件和目录,-x 选项会恢复它们的原始结构。
-t用于显示归档文件中包含的文件和目录列表,而不实际提取它们。这对于检查归档内容非常有用,而无需解压整个归档。
-u用于将新文件添加到已存在的归档文件中,或者更新归档中已存在的文件。如果归档文件不存在,tar 会创建一个新的归档文件。
-v会在执行操作时显示更多的信息,例如正在处理的文件名。这对于跟踪 tar 命令的进度和调试问题非常有用。
-f用于指定归档文件的名称。-f 选项必须紧跟归档文件名,不能有空格。如果指定的文件名已存在,tar 会根据其他选项(如 -c-x)来决定是覆盖还是追加文件。
-z用于在创建归档时使用 gzip 进行压缩,或在提取归档时使用 gzip 解压缩。-z 选项允许 targzip 协同工作,创建 .tar.gz.tgz 格式的压缩归档文件。
-j用于在创建归档时使用 bzip2 进行压缩,或在提取归档时使用 bzip2 解压缩。-j 选项允许 tarbzip2 协同工作,创建 .tar.bz2 格式的压缩归档文件。

tar 命令的 -z-j 选项分别用于指定使用 gzip 和 bzip2 进行压缩。如果没有指定这些压缩选项,tar 将仅执行打包操作而不进行压缩。

参数作用
FILE一个或多个文件或目录。这些文件或目录可以是具体的文件名,也可以是通配符,如 *.txt,表示所有以 .txt 结尾的文件。

示例:

  1. 将多个文件打包成 .tar 文件(不压缩)

    shell
    [root@localhost ~]# tar -cvf archive.tar /etc/passwd /etc/shadow
    tar: Removing leading `/' from member names
    /etc/passwd
    tar: Removing leading `/' from hard link targets
    /etc/shadow

    tar: Removing leading '/' from member names:这条信息表明 tar 在打包过程中自动移除了文件路径中的前导斜杠 /。这是 tar 的标准行为,目的是为了在解压缩时提供更大的灵活性。如果不移除这些斜杠,那么归档中的文件路径将会是绝对路径,这可能会导致在不同系统或目录下解压缩时出现问题。

    tar: Removing leading '/' from hard link targets:这条信息表明 tar 在处理硬链接时也移除了前导斜杠 /。硬链接是文件系统中的链接,指向相同的文件内容。当一个文件被硬链接到另一个位置时,它们共享相同的数据块,因此任何对文件内容的修改都会反映在所有硬链接上。在 tar 打包过程中,如果 /etc/shadow 文件被硬链接到其他位置,tar 会记录这些硬链接的目标文件路径。由于 tar 默认移除前导斜杠 /,所以硬链接的目标路径也会被相应地调整。

    shell
    [root@localhost ~]# ll archive.tar 
    -rw-r--r--. 1 root root 10240 Nov 22 11:38 archive.tar
  2. 查看和提取归档文件中的内容

    shell
    [root@localhost ~]# tar -tvf archive.tar 
    -rw-r--r-- root/root       892 2024-11-18 08:51 etc/passwd
    ---------- root/root       579 2024-11-18 08:53 etc/shadow

    这个文件 archive.tar 是一个由 tar 命令创建的归档文件,但没有经过压缩。可以通过以下命令提取这个归档文件的内容到当前目录:

    shell
    [root@localhost ~]# tar -xvf archive.tar
    etc/passwd
    etc/shadow
    shell
    [root@localhost ~]# ll etc/
    total 8
    -rw-r--r--. 1 root root 892 Nov 18 08:51 passwd
    ----------. 1 root root 579 Nov 18 08:53 shadow

    如果想要将归档文件中的内容提取到一个指定的目录,可以使用 -C 选项(代表“change directory”,即改变目录)来指定目标目录:

    shell
    [root@localhost ~]# tar -xvf archive.tar -C /opt/
    etc/passwd
    etc/shadow
    shell
    [root@localhost ~]# ll /opt/etc/
    total 8
    -rw-r--r--. 1 root root 892 Nov 18 08:51 passwd
    ----------. 1 root root 579 Nov 18 08:53 shadow
  3. 使用 gzip 压缩的归档文件

    shell
    [root@localhost ~]# tar -czvf etc.tar.gz /etc/

    执行这个命令后,/etc/ 目录下的所有文件和子目录将被打包并压缩到名为 etc.tar.gz 的归档文件中。这个归档文件将位于执行命令的当前目录,在这个例子中是 /root 目录。

    如果想要一次性将 gzip 压缩的 tar 归档文件提取并解压缩到当前目录,可以使用以下命令:

    shell
    [root@localhost ~]# tar -xzvf etc.tar.gz
  4. 使用 bzip2 压缩的归档文件

    需要注意,Rocky 默认没有安装 bzip2 压缩工具的,需要手动安装:

    shell
    [root@localhost ~]# dnf -y install bzip2

    安装完成后 tar 可以使用 bzip2 进行压缩了:

    shell
    [root@localhost ~]# tar -cjvf var.tar.bz2 /var/

    要解压这个使用 bzip2 压缩的归档文件 var.tar.bz2,可以使用以下命令:

    shell
    [root@localhost ~]# tar -xjvf var.tar.bz2

    执行这个命令后,var.tar.bz2 中的内容将被解压并提取到执行命令的当前目录中。如果归档文件中包含目录结构,这些目录和文件将按照它们在归档中的结构被重建。

  5. 更新与删除归档文件

    更新归档文件意味着想要将新文件添加到现有的归档中,或者更新归档中已经存在的文件。tar 命令使用 -u 选项来更新归档文件:

    shell
    [root@localhost ~]# tar -uvf archive.tar text.txt 
    text.txt

    执行上述命令后,text.txt 文件将被添加到 archive.tar 归档中:

    shell
    [root@localhost ~]# tar -tvf archive.tar 
    -rw-r--r-- root/root       892 2024-11-18 08:51 etc/passwd
    ---------- root/root       579 2024-11-18 08:53 etc/shadow
    -rw-r--r-- root/root        10 2024-11-29 09:54 text.txt

    要从 tar 归档文件中删除文件,可以使用 --delete 选项。这个选项允许指定一个或多个文件,这些文件将从归档中删除。请注意,这个操作会直接修改归档文件:

    shell
    tar -vf archive.tar --delete text.txt
    shell
    [root@localhost ~]# tar -tvf archive.tar
    -rw-r--r-- root/root       892 2024-11-18 08:51 etc/passwd
    ---------- root/root       579 2024-11-18 08:53 etc/shadow

    WARNING

    对于使用 tar 创建的压缩包(如 .tar.gz.tar.bz2),tar 命令本身不支持直接进行更新和删除操作。这是因为压缩归档文件是一个整体,tar 命令没有提供直接修改压缩归档内容的功能。