文件的压缩是非常重要和常见的操作。

在 Windows 下,zip 和 rar 经常使用的压缩软件,框选一堆文件,右键用 WinRAR 就可以完成压缩。不过在 linux 下通常不这么做。一是因为 linux 的压缩指令针对单个文件,将多个文件合为一个文件被称为“打包”,打包和压缩是分离的(其实 Win 下很多时候压缩文件目的主要也是打包而不是压缩嘛);二是因为 zip 和 GNU 不是一家的,所以 zip 不能完整保存压缩后文件的 rwx 等权限。

linux 常用的压缩工具有 gzip, bzip2, xz。

压缩

gzip, bzip2, xz 都是压缩单个文件的指令,通常压缩的文件以*.gz、*.bz2 或者 *.xz 作为文件名。这三个命令出现的时间越来越晚,压缩算法也越来越先进,用法基本相同,这里用 gzip 为例介绍他们。

$ gzip -选项 文件名
-c:将压缩文件通过管道输出
-v:压缩时控制台打印压缩信息
-d:解压缩参数
-1:数字表示压缩等级1-9,等级越高压缩时间越长,压缩比越好
-k:压缩后不删除源文件(默认删除)
$ gzip 1.cpp # 生成了 1.cpp.gz,源文件被删除
$ gzip -d 1.cpp.gz # 文件还原了,也可用 gunzip

要查看压缩文件的内容(如果是文本文件),无需解压缩,使用 zcat/zless/zgrep 直接查看压缩文件即可(与 cat/less/grep 对应);如果是 bzip2 文件就用 bzcat,xz 使用 xzcat。

打包

压缩指令只针对一个文件,打包 tar 可以将多个文件合成一个文件,所以压缩包常常是 .tar.gz 和 .tar.bz2 等形式。不过 tar 命令本身也承担的压缩的功能,他可以在打包完成后自动压缩。

$ tar [-zjJ]-其他命令 -f 文件名
-f:指定操作的文件名
-zjJ:z 表示使用 gzip 压缩,j 表示 bzip2,J 表示 xz。这是三选一的关系
-v:打包压缩时控制台打印信息
-p:保存数据的权限属性
-c:创建压缩包
-t:查看压缩包
-x:解压
$ tar -zcvf ./save.gz ./ # 当前目录打包到 save.gz
$ tar -ztvf ./save.gz # 查看
$ tar -zxvf ./save.gz # 解压缩

压缩的根目录问题:

同一个目录,用不同的路径写他,压缩文件里保存的路径也不一样

tar -vczf save.gz learngit
tar -vczf save.gz ../ofnoname/learngit
tar -vczf save.gz /home/ofnoname/learngit

tar -tzf save.gz # 查看压缩文件

第一个命令,压缩 learngit 文件夹,查看里面的内容,都是 learngit/xxx 的形式。而第二个命令,压缩出现提示"tar: 从成员名中删除开头的“../”",查看里面的内容,都是 ofnoname/learngit/xxx 的形式。第三个则没有了 / ,成为了home/ofnoname/learngit。

问题在于,如果你在一个地方解压缩文件,肯定是希望在当前目录下再出现一个文件夹来放置解压后的文件的,如果保留了../ofnoname/learngit,解压的时候就文件冒到上一个文件夹了;要是保留了/home/ofnoname/learngit,那更不得了,解这个压缩包文件就会直接出现在根目录了。

所以压缩的时候,默认会去除绝对目录,保证整个压缩包里是一个不能往上返回的相对目录,不过也可以使用 -P 保留原路径。