在日常工作中,我们有时需要对文件或文件夹进行打包和压缩以方便传输和存储,我们主要使用tar、gzip、bzip2、xz和zip命令完成这些操作。
首先要注意几个概念:
打包 (Tarballing): 将多个文件或目录合并成一个文件,但不减少其占用空间。例如,tar命令。
压缩 (Compression): 利用算法减小单个文件的体积。例如,gzip, bzip2, xz命令。
通常所说的"压缩"往往指的是先打包再压缩的组合操作,例如 .tar.gz 文件。
一、tar命令
tar是最常用的linux打包和压缩工具,注意tar命令在不使用-z -j -J调用压缩命令时,仅仅进行打包,不会进行压缩。
| 参数 | 含义 | 使用场景 |
|---|---|---|
-c |
Create,创建新的归档文件 | 打包并压缩文件夹 |
-x |
eXtract,解压/提取归档文件 | 恢复备份或安装软件包 |
-t |
Table, 列出归档文件内容 | 查看包内文件列表,无需完全解压 |
-f <filename> |
File, 指定归档文件名 | 必选项,指定要操作的.tar文件,该参数一般放最后 |
-v |
Verbose, 显示处理过程 | 实时查看哪些文件正在被处理(可选) |
-z |
调用 gzip 进行 Zlib压缩/解压 |
生成 .tar.gz 或 .tgz 文件,最常用 |
-j |
调用 bzip2 进行压缩/解压 |
生成 .tar.bz2 文件,高压缩率 |
-J |
调用 xz 进行压缩/解压 |
生成 .tar.xz 文件,最高压缩率 |
-C |
指定解包/解压的目标目录路径 | 将打包/压缩文件解压至目标文件夹 |
-p |
保留源文件权限 | 不改变文件的属性,如只读 |
-P |
保留源文件的文件路径 | 如打包/etc/shadow文件,解包会自动解至原路径,注意容易覆盖当前文件导致当前文件丢失 |
示例:
1.备份项目代码 (打包并压缩)
场景: 每周备份 /data/project/webapp 目录,并以当前时间命名(格式%Y%m%d)。
powershell
tar -czvf webapp_backup_$(date +%Y%m%d).tar.gz /data/project/webapp
c: 创建新归档。
z: 使用 gzip 压缩。
f: 指定文件名为 webapp_backup_20260323.tar.gz (利用 date 命令动态生成带日期的文件名)。
/data/project/webapp: 要打包的源目录。
2.解压部署包
场景: 在服务器上解压 myapp.tar.gz 到 /opt/ 目录下。
powershell
cd /opt/
tar -xzvf myapp.tar.gz
或:
tar -xzvf myapp.tar.gz -C /opt/myapp
x: 提取文件。
z: 解压 gzip 格式。
f: 指定要解压的文件 myapp.tar.gz。
C:指定解压到/opt下
3.仅查看压缩包内容
场景: 在解压前,想确认 myapp.tar.gz 里有什么文件,避免解压错误覆盖。
powershell
tar -tzf myapp.tar.gz
t: 列出内容。
z: 对 gzip 格式进行操作。
f: 指定文件。
4.增量备份与排除特定文件
场景: 备份 /var/log 日志,但排除旧的日志轮转文件。
powershell
tar -czvf logs_current_$(date +%Y%m%d).tar.gz --exclude='*.gz' /var/log/
解释: --exclude 参数可以排除匹配模式的文件,备份时过滤掉临时文件、缓存或旧文件。
二、zip命令
.tar、.tar.gz等格式在windows中并不常见(但linux区分文件类型不依赖后缀名,后缀名仅为使人类方便查看),windows中更多的是.zip或.rar格式的压缩文件,为了更方便地传输文件,还可以使用zip命令,zip 是一个将打包和压缩合二为一的工具。它的最大优势在于通用性------无论是 Windows、macOS 还是 Linux,都能原生支持 .zip 格式。
| 参数 | 含义 |
|---|---|
-r |
递归处理目录 |
-d |
从压缩包中删除文件 |
-u |
更新压缩包中的文件 |
-m |
移动文件到压缩包 |
-e |
设置密码加密 |
示例:
1.压缩文件/目录: 压缩目录时加 -r(递归)处理子文件夹。
powershell
zip -r test.zip /path/to/directory
2.解压文件: 使用 unzip 命令。
powershell
unzip test.zip
3.指定解压路径: 使用 -d 参数。
powershell
unzip test.zip -d /path/to/unzipdirectory
4.查看压缩包内容: 不解压,直接查看。
powershell
unzip -l test.zip
三、gzip bzip2 xz命令
这三个命令多数结合tar命令使用,但也可单独使用。
3.1 gzip
gzip 是 Linux 世界中最古老的压缩标准之一。它的特点是速度快,兼容性极好,几乎所有的 Linux 发行版都默认支持。
常用参数:
-k:保留原始文件,不删除源文件。
-d:解压文件。
-r:递归处理目录(但 gzip 本身不支持直接压缩目录,通常配合 tar 使用)。
-v:显示压缩过程。
-1 到 -9:设置压缩级别,-1 最快但体积大,-9 最慢但体积小。
示例:
1.压缩单个文件:
gzip filename.txt
结果:生成 filename.txt.gz,原文件会被删除
2.保留原文件进行压缩: 加上 -k 参数。
gzip -k filename.txt
#结果:生成 filename.txt.gz,同时保留 filename.txt
3.不解压直接查看内容: 使用 zcat 或 zless。
zcat filename.txt.gz
3.2 bzip2
随着文件越来越大,gzip 的压缩率有时显得不够用,这时 bzip2 就登场了。它采用了更复杂的算法(Burrows-Wheeler),能在 gzip 的基础上进一步减小文件体积。
常用参数:
-k:保留原始文件。
-d:解压文件。
-v:显示压缩过程。
-z:压缩(默认)。
-t:测试文件完整性。
3.3 xz
xz 是较新的压缩工具。它拥有目前主流工具中最高的压缩率。如果你需要分发大型源码包或备份冷数据,xz 是很好的选择。
常用参数:
-k:保留原始文件。
-d:解压文件。
-z:压缩(默认)。
-v:显示压缩过程。
-0 到 -9:压缩级别,-9 为最高压缩率。
四、注意
4.1 tar在打包过程中不会进行压缩,但有时会出现打包后文件大小发生改变的情况,原因可能如下:
- 打包的对象是"稀疏文件"
这是最常见导致"体积变小"的原因。
什么是稀疏文件:有些文件(如虚拟机磁盘镜像、某些数据库文件)内部包含大量的"空洞"(全是 0 的数据块)。在硬盘上,系统只记录"这里有 1GB 的空洞",而不真正占用 1GB 的磁盘空间。
tar 的处理:当你打包这类文件时,tar 会智能地只记录这些"空洞"的元数据,而不把它们变成实打实的 0。
结果:假设你有一个 10GB 的虚拟机镜像文件,但在硬盘上只占了 2GB(因为大部分是空的)。打包后,.tar 文件可能只有 2GB 多一点。
错觉:你以为它压缩了,其实它只是忠实地记录了"空洞"。 - 你打包的是"大量小文件"
文件系统的"块"效应:Linux 文件系统(如 ext4)有一个"块大小"(通常是 4KB)。哪怕你有一个只有 1 字节的文件,它也会占用 4KB 的磁盘空间。这叫"内部碎片"。
tar 的处理:tar 把文件流式地写入,它不需要像文件系统那样为每个小文件分配一个"块"。
结果:如果你有 10,000 个 1 字节的小文件,在硬盘上它们可能占用 40MB(10000 * 4KB)。但打包成 .tar 后,文件总大小可能只有 10KB(实际数据)+ 少量的头部信息。
错觉:打包后的体积竟然比源文件占用的磁盘空间还小!这是因为 tar 消除了文件系统的"内部碎片"。 - 你查看的是"显示大小"而非"实际占用"
在 Linux 中使用 ls -l 命令查看时,它显示的是文件的逻辑大小(内容长度)。
如果你用 du -sh 命令查看,它显示的是实际占用磁盘块的大小。
对于普通文件,tar 打包后的逻辑大小通常等于(甚至略大于)所有源文件的逻辑大小之和。
测试:
如果你有 10,000 个 1 字节的小文件,在硬盘上它们可能占用 40MB(10000 * 4KB)。但打包成 .tar 后,文件总大小可能只有 10KB(实际数据)+ 少量的头部信息
powershell
# 1. 准备环境:创建一个测试目录并进入
mkdir -p small_file_test && cd small_file_test
# 2. 制造"空间黑洞":生成 10,000 个 1 字节的小文件
# 为了速度,我们使用循环批量写入
for i in {1..10000}; do echo -n "a" > file_$i.txt; done
# 3. 查看文件的"逻辑大小"(看起来的大小)
du -b . | head -1 # 显示当前目录所有文件的实际字节总和(约 10KB+)
# 4. 查看文件的"磁盘占用"(实际吃掉的硬盘空间)
du -sh . # 显示当前目录在硬盘上实际占用的空间(约 40MB+)
# 5. 执行打包(不加压缩)
tar -cvf bundle.tar .
# 6. 查看打包后的文件大小
ls -lh bundle.tar

4.2 解压时报错
五、练习
在练习之前,先执行脚本生成一个练习环境。
powershell
#!/bin/bash
# 1. 创建目录结构
mkdir -p /data/tar_lab/project/{src,conf,logs,data}
mkdir -p /data/tar_lab/backup
# 2. 创建源代码文件
echo "int main() { return 0; }" > /data/tar_lab/project/src/main.c
echo "#include <stdio.h>" > /data/tar_lab/project/src/utils.h
# 3. 创建配置文件
echo "db_host=localhost" > /data/tar_lab/project/conf/app.conf
echo "port=8080" >> /data/tar_lab/project/conf/app.conf
# 4. 创建大量日志 (模拟大文件,约 40KB)
for i in {1..1000}; do echo "Log entry $i: System running normally..." >> /data/tar_lab/project/logs/app.log; done
# 5. 创建数据文件
echo "User Data 1" > /data/tar_lab/project/data/user.db
echo "User Data 2" > /data/tar_lab/project/data/admin.db
# 6. 创建一个空目录
mkdir -p /data/tar_lab/project/temp_cache
# 7. 创建一个测试用etc
mkdir -p /data/etc/conf.d
echo "test" > /data/etc/config.txt
# 7. 创建一个软链接 (模拟指向外部配置)
touch /data/etc/hostname
ln -s /data/etc/hostname tar_lab/project/conf/host_link
echo " 练习环境已生成!请进入 tar_lab 目录开始练习。"
题目 1:基础打包
场景:你需要将 project 目录打包成一个名为 project_bundle.tar 的文件,但不需要压缩。
要求:能够看到打包过程的详细信息。
powershell
答案与解析:
tar -cvf project_bundle.tar project/
解析:-c 表示创建归档,-v 显示过程,-f 指定文件名。注意此时文件体积会很大,因为包含了日志文件。
题目 2:Gzip 压缩
场景:为了节省空间,你需要将 project 目录打包并使用 gzip 压缩。
要求:生成 project.tar.gz 文件。
powershell
答案与解析:
tar -zcvf project.tar.gz project/
解析:-z 调用 gzip 算法。这是 Linux 运维中最常见的命令组合,兼顾了速度与压缩率。
题目 3:指定目录解压
场景:你下载了一个源码包,不想让它解压到当前目录弄乱桌面,而是想直接解压到 backup 目录中。
要求:不进入 backup 目录,直接解压进去。
powershell
答案与解析:
tar -zxvf project.tar.gz -C backup/
解析:-C 用于切换目录。这是部署软件时的常用技巧,可以直接将文件释放到目标安装目录。
题目 4:排除特定文件
场景:你要备份 project 目录,但是 logs/app.log 这个日志文件太大了,你不需要备份它。
要求:打包时排除 project/logs 目录。
powershell
答案与解析:
tar -zcvf project_no_logs.tar.gz --exclude='project/logs' project/
解析:--exclude 是运维备份时的神器。你也可以使用通配符,例如 --exclude='*.log'。对比一下生成的文件大小,你会发现这个包小了很多。
题目 5:保留绝对路径与权限
场景:假设你在备份系统配置文件。你需要保留文件的绝对路径(即解压后还是在 / 下),并且保留文件的原始权限(如只读属性)。
powershell
答案与解析:
tar -zcvpf backup_etc.tar.gz -P etc/
解析:-p 保留文件权限,-P 保留绝对路径。警告:在生产环境使用 -P 需极度小心,因为解压时可能会覆盖系统文件。
题目 6:只解压其中一个文件
场景:project.tar.gz 包里有很多文件,但你只把 conf/app.conf 配置文件改坏了。你不想解压整个包,只想把这一个文件"捞"出来恢复。
powershell
答案与解析:
# 1. 先查看包内文件路径(防止路径写错)
tar -tvf project.tar.gz | grep app.conf
# 2. 解压指定文件
tar -zxvf project.tar.gz project/conf/app.conf
解析:直接跟上文件在压缩包内的相对路径即可。这比解压整个包要快得多,尤其是在处理几个 G 的备份包时。
题目 7:不解压直接查看内容
场景:你想确认 project.tar.gz 里面到底有哪些文件,或者想看看 app.conf 的内容,但完全不想解压它。
powershell
答案与解析:
# 1. 查看文件列表
tar -tvf project.tar.gz
# 2. 查看具体文件内容 (配合管道)
tar -zxOf project.tar.gz project/conf/app.conf
解析:-t 列出归档内容,-O 将文件内容输出到标准输出(屏幕)。
题目 8:处理 Bzip2 和 Xz 格式
场景:为了追求极致压缩率,你需要将 project 目录打包成 .tar.bz2 和 .tar.xz 格式。
powershell
答案与解析:
# 1.bzip2 (参数 -j)
tar -jcvf project.tar.bz2 project/
# xz (参数 -J,注意大写)
tar -Jcvf project.tar.xz project/
解析:z 是 gzip,j 是 bzip2,J 是 xz。现代 Linux 的 tar 通常能自动识别格式,解压时直接 tar -xvf 即可。
题目 9:基于时间戳的增量备份(利用 mtime)
在 Linux 中,文件有三个核心时间属性:mtime(修改时间)、ctime(改变时间)、atime(访问时间)。
场景:你周一做了全量备份。周二到周五,只有部分文件被修改了。
要求:找出 project 目录下,在过去 24 小时内被修改过(mtime 更新)的文件,并单独打包。
powershell
答案与解析:
# 1.方法一:使用 find 配合 tar
find project/ -type f -mtime -1 | xargs tar -cvf daily_backup.tar
# 2.方法二:使用 tar 的内置时间过滤
tar -cvf daily_backup.tar --newer-mtime='1 day ago' project/
解析:mtime 是判断文件是否发生变化、是否需要备份的最重要依据。--newer-mtime 告诉 tar 只打包那些内容比指定时间更新的文件。
题目 10:处理软链接
场景:project 目录下有一个软链接 conf/host_link 指向 /data/etc/hostname。
要求:打包时,你想把软链接本身打包进去(解压后还是个链接),而不是把 /etc/hostname 的真实文件内容打包进去。
powershell
答案与解析:
# 1.默认行为就是打包软链接本身,什么都不用加
tar -cvf softlink_backup.tar project/
# 2.或者显式声明"不要解引用"(更严谨)
tar -cvf softlink_backup.tar --no-dereference project/
解析:默认情况下,tar 只保存链接的路径。如果你加上 -h(dereference),tar 就会把链接指向的真实文件内容打包进去。
题目 11:向已有的压缩包追加文件
场景:你刚打包好 project_bundle.tar(注意是未压缩的 tar 包),突然发现漏了一个 readme.txt 文件。
要求:在不解压、不重新打包整个目录的情况下,把 readme.txt 加进去。
powershell
答案与解析:
# 注意:只能对 .tar 格式直接追加,压缩格式需特殊处理
tar -rvf project_bundle.tar readme.txt
解析:-r 表示追加。陷阱在于:这只能用于未压缩的 .tar 包。如果是 .tar.gz,通常建议重新打包,因为压缩流是连续的,无法在中间插入数据。
题目 12:流式传输(网络备份)
场景:你想把本地 project 目录打包,直接通过网络发送给另一台服务器,而不想在本地生成中间文件。
powershell
答案与解析:
# 将打包数据通过管道传给 ssh,直接写入远程服务器
tar -cvf - project/ | ssh user@192.168.1.100 "cat > /tmp/remote_backup.tar"
解析:tar -cvf - 中的 - 代表标准输出。配合管道符,数据不经过硬盘,直接通过网络传输并写入远程文件。
题目 13:保留原始修改时间
场景:你备份了一个旧项目。默认情况下,tar 解压时会恢复归档中保存的时间戳。但在某些特殊脚本中,你可能需要强制控制这一行为。
要求:解压文件,但强制使用"当前时间"作为文件的 mtime(即不保留原始时间)。
powershell
答案与解析:
tar -zxvf project.tar.gz -m
解析:-m 参数告诉 tar 在提取时不要恢复文件的时间戳,而是使用解压时的当前时间。这在某些需要触发基于时间戳的构建系统(如 Make)重新编译时非常有用。
题目 14:打包后修改压缩包时间
场景:你生成了一个备份包 backup.tar.gz,为了方便管理,你希望这个压缩包文件的修改时间(mtime)显示为"昨天"。
powershell
答案与解析:
# 使用 touch 命令修改文件时间戳
touch -d "yesterday" backup.tar.gz
解析:虽然这不是 tar 命令,但这是配合归档管理的必备技能。touch -d 可以设置任意时间,让文件列表看起来整洁有序。