资讯动态

tar与压缩工具全解析:从打包、解压到备份的实战技巧

发布时间:2026/10/19 8:01:56 来源:尧图企业网站定制
打包压缩这些命令平时用起来好像谁都会敲两下可真到服务器上处理几个G的日志、迁移整个项目目录、给客户交付一批素材的时候就会发现里面的门道比想象中多得多。这篇文章我就把文件处理里最常用的打包压缩这块掰开揉碎讲一遍既说清楚每个命令的原理也把我这些年实际踩过的坑和经验一并交代出来。1. 先搞清楚打包和压缩其实是两件事很多刚接触这块的朋友会把“打包”和“压缩”混为一谈但这两个动作在计算机里是完全不同的概念。打包Archive是把多个文件和目录合并成一个文件它解决的是“怎么把一堆东西归拢到一起”的问题压缩Compress则是通过算法把文件的冗余信息去掉解决的是“怎么让体积变小”的问题。之所以要区分开是因为这两个操作背后的命令和工具本来就不是一回事。在早期的Unix系统里tarTape Archive的缩写负责归档打包它最初的设计目标是把文件写到磁带上去备份压根不负责压缩。而压缩是gzip、bzip2、xz这些工具干的活。所以你看tar命令的参数里-z、-j、-J这些选项实际上是“调用外部压缩工具”的开关而不是tar自己实现了压缩算法。理解了这一点很多使用习惯就顺理成章了。比如你看到tar -czvf这样的组合心里就应该清楚tar先把文件归拢成一个包再通过管道把数据流交给gzip去压缩。为什么tar不自己内置压缩功能非要调用外部工具这正是Unix哲学“一个工具只做一件事但把这件事做到极致”的体现。tar只需要管好归档逻辑就够了压缩算法的更新换代完全由专门的压缩工具去演进彼此不拖后腿。这个设计还有个实际好处压缩工具是可以灵活替换的。你想追求速度就用gzip想极限压体积就用xz想兼顾兼容性就用bzip2tar本身不用变换个参数就行。这种解耦的思维在Linux生态里到处都是理解了tar和压缩工具的关系你后续看很多软件设计思路都会有豁然开朗的感觉。另外再补充一个很多人不知道的细节像tar -czf和tar -cf | gzip这样的写法底层做的事情几乎是一样的。tar把归档数据写到标准输出gzip从标准输入读取数据然后压缩到文件里本质上是一条管道协作。所以如果你看到有人在脚本里用管道分开写不用觉得奇怪那其实就是tar自带-z选项展开后的形态。2. 最核心的tar命令从创建到解压一次讲透2.1 创建打包文件时的参数组合怎么选tar命令是打包压缩这块的重中之重可以说80%的日常操作都在围绕它进行。先来看创建打包文件也就是“把一堆东西归拢成一个文件”这个方向。最基础的命令是tar -cf archive.tar file1 file2 dir1/这里的-c表示创建一个新的归档文件-f后面跟的是归档文件名。这个命令执行完你会得到一个archive.tar它把所有列出的文件和目录都收进去了但体积基本没变因为没有压缩。想压缩的话加上-z调用gziptar -czf archive.tar.gz file1 file2 dir1/这套命令组合是日常中使用频率最高的一组。但你需要注意-z是调用gzip它的压缩速度很快压缩率属于中等水平。如果换用-j那就是调bzip2压缩率比gzip高但速度会慢不少。再往上追求压缩率用-J调xz压缩率最高但速度也最慢尤其对几十G的大目录来说压缩时间可能以小时计。这里有一个我自己的使用习惯临时传文件、做快速备份的时候一律用tar -czf图个速度快、兼容性好做长期归档、冷存储备份的时候才用tar -cJf因为xz在极高压缩率的同时解压速度也没有慢到不能接受的地步。至于-j配合bzip2我在实际工作中用得越来越少因为它的压缩率没有比gzip强太多速度却慢了一大截有点两头不占。还有-v参数代表verbose就是让tar把正在处理的文件名打印到屏幕上。刚上手的时候建议加上你能直观看到归档进程走到哪了、有没有漏掉文件。但脚本里自动化执行的时候我一般不加-v因为文件一多输出量太大反而影响效率而且日志会刷屏。2.2 解压和查看内容时的高频用法解压一个tar包最常用的命令是tar -xzf archive.tar.gz这里-x代表extract也就是解压归档。和创建对称的是解压同样需要根据压缩格式选择对应的选项gzip用-zbzip2用-jxz用-J。如果你不确定这个包是什么格式压的其实有个更省心的办法tar -xf archive.tar.gz新版tarGNU tar 1.27以上版本支持自动检测压缩格式你只要用-xf它自己会判断该用什么解压器不需要额外指定z/j/J。这个特性在日常使用中非常省事也避免了“明明包是xz压的我却非要用-z去解”这种尴尬报错。但如果你解压之前想先看看包里都有什么东西不想真的解出来那就用-t参数tar -tzf archive.tar.gz它会把归档里的文件列表列出来不解压文件内容。这个命令我用的频率相当高尤其是从网上下载了一些包、或者接手同事留下的压缩包时先看一眼里面的目录结构再决定怎么解压。不然万一包里所有文件都散落在根目录不先建个子目录的话会直接解到你当前目录里把现有文件混得一团糟。解压到指定目录也是刚需操作用-C参数tar -xzf archive.tar.gz -C /target/dir/-C代表change directory意为切换到目标目录后再执行解压。这个参数我用得极多因为解压到指定位置几乎成了每次都会做的事。需要注意的是目标目录必须已经存在否则tar会直接报错它不会帮你创建目录。2.3 为什么-f必须放在参数最后这个点我拿不准该说多少遍才能让大家真正记住。tar命令的参数有一个语法特点其他选项可以合并写在一起但-f后面必须紧跟着文件名。所以tar -cf archive.tar是合法的tar -fc archive.tar就会出问题——tar会把archive.tar当成一个选项来解析然后报错退出。这个排序问题之所以容易出错是因为很多人图省事会把字母随便排一下。我自己早期就吃过这个亏当时写了个tar -xzf target.tar.gz -C /path看起来没毛病但实际执行后tar提示“f: Cannot open: No such file or directory”我又检查了好几遍文件名最后才意识到是参数顺序的问题。后来我总结了一个经验永远把-f当作“最后一个参数”来记不管是创建还是解压写参数的时候先写cv/jxz这些功能选项最后再写-f和文件名。这个习惯养成了能帮你少踩很多这种低级但抓狂的坑。另外一个容易忽略的点是当-f后面接的是-单个减号时表示tar的数据走标准输入输出通常用于管道流。比如tar -czf - dir1/ | ssh userremote cat backup.tar.gz这条命令在本地把dir1打包压缩输出的是一个数据流通过管道交给ssh在远程服务器上写入文件。这种玩法在网络传输场景下特别有用它跳过了“本地落地一个文件再上传”的中间步骤让你不用在磁盘上腾出临时空间。对磁盘紧张、文件又很大的场景来说这真的是一个救命技巧。2.4 几个解压和归档时的高阶选项先说说排除文件这个功能在实战中可以说是最常用到的高阶选项。如果你想备份一个项目目录但不想把里面的node_modules、.git、日志文件都塞进包里就可以用--excludetar -czf project_backup.tar.gz --excludenode_modules --exclude.git --exclude*.log project/这个选项可以写很多次每次都指定一个排除模式。它要是没注意的坑在于排除模式是相对于当前执行tar命令的路径而言的不是相对于包内路径。比如你在/home/user/目录下打包project文件夹想排除project下的node_modules就要写--excludeproject/node_modules或者先用-C切到project的上级目录再写--excludeproject/node_modules这个模式。我见过不少人在这里栽跟头明明排除了模式结果发现文件还是进包了就是因为路径写法不对。再有就是保留文件权限和属性。默认情况下tar打包是保留文件权限位的但在解压时如果是普通用户执行可能会因为umask设置导致权限变化。想要严格保留原始权限、属主、时间戳这些元数据推荐用-p参数。做系统迁移、备份其他用户目录时这个参数格外重要。我曾经在迁移一个服务目录时没有用-p结果解压出来的文件属主全变成了当前用户服务起不来排查了半天才发现是文件属主的问题。还有一个容易忽视的是-P参数代表保留绝对路径。默认情况下tar会把归档路径中的根目录/去掉这是处于安全考虑的设计防止解压时直接覆盖掉系统的绝对路径文件。但如果你明确需要打包时保留绝对路径比如备份/etc下的配置文件想解压出来直接覆盖到/etc下那就可以加-P。不过这个选项要慎用万一路径写错了解压可能覆盖系统的关键文件操作前务必确认路径准确无误。3. 除了tar这些压缩工具也得用明白3.1 gzip、bzip2、xz到底有什么区别虽然tar是我们使用最频繁的归档工具但gzip、bzip2、xz这些独立的压缩工具本身也经常需要直接使用比如压缩单个文件、解压一个.log.gz的日志等。这里我干脆把它们的区别讲透。gzip是最普及的压缩工具几乎每个Linux发行版都会默认安装。它的压缩速度比较快压缩率中规中矩日常使用没有任何兼容性问题。你会看到大量以.gz为后缀的文件特别是系统日志轮转、软件源码包基本都是gzip。但它有一个限制只能压缩单个文件无法归档目录。所以你在日常中如果想要压缩一个目录gzip没办法一步到位必须配合tar。bzip2在压缩率上比gzip高一些在文本文件上效果更明显但压缩速度相对较慢。前几年它还挺风靡的源码包很多都用.bz2后缀但这些年xz已经逐步取代了它的位置因为xz在压缩率上做得更极致。xz是这三者里压缩率最高的代价是压缩时的计算开销也最大。它的解压速度倒是不算太慢所以用在“压缩一次、解压多次”的归档场景里非常合适。现在Linux内核源码的压缩包就是以xz为主足以说明它的地位。说句实话如果你没有极端压缩率需求日常用gzip就够了。压缩率提升带来的体积缩小可能只换来了一点存储空间却要付出几倍的压缩时间。到底值不值得看场景。我自己给客户交付大文件时会优先选择zip格式因为所有人都能轻松解压给自己备份数据时才用tar xz因为可以压出最小体积。3.2 不同压缩等级怎么设置gzip、bzip2、xz都支持压缩等级参数从1到9等级越高压缩率越好但速度越慢。以gzip为例gzip -1 file # 最快的速度压缩率最低 gzip -6 file # 默认等级速度与压缩率均衡 gzip -9 file # 最慢速度压缩率最高这条经验相当实际。如果你只是临时压缩一下再传给别人用-1能省下大量时间如果是做归档存储那就用-9充分压体积。我以前压缩一批约10GB的日志文件时做过对比-1压缩只用了几十秒-9要跑十分钟以上但两者压缩后的体积差别其实没到不可接受的地步。所以做配置的时候先搞清楚你是吃时间还是吃空间再去选等级。xz同样有等级参数而且它还有一个额外的优势-T参数可以指定多线程让压缩过程利用多核CPU。这在压缩大文件时提升极大比如xz -T 0 -9 bigfile-T 0表示自动使用所有可用核心。如果你手里是台多核服务器用这个选项可以显著缩短等待时间。不过要注意bzip2和gzip不支持多线程压缩它们的并行版本是lbzip2、pigz属于第三方实现单线程跑大文件确实会让人等得很着急。说到pigz它是gzip的并行实现压缩时能充分利用多核。如果你的环境允许安装额外工具强烈建议备一个pigz配合tar使用的方式是tar -cf - project/ | pigz -9 project.tar.gz不要觉得这个操作很绕实际上它就是用管道把tar的输出交给pigz压缩效果等同tar -czf project.tar.gz project/但压缩速度大幅提升。我处理几个G的项目目录打包时经常这么玩时间能缩短一半以上。3.3 zip在跨平台场景下的特殊地位如果你工作的环境经常和Windows用户打交道那zip的生态优势就体现出来了。Windows系统自带对zip格式的支持右键就能解压不需要安装任何额外软件。这决定了在很多交付场景下zip是唯一稳妥的选择。Linux下创建zip的常用命令是zip -r archive.zip dir1/ file1-r代表递归把目录里的内容也一并加进来。这个参数不能漏否则zip只会把一个空目录打进去。解压zip包用unzip命令unzip archive.zip如果用unzip解压时遇到中文文件名乱码那是因为zip文件里的中文编码是GBK而Linux默认使用UTF-8解析。这时可以用unzip -O GBK archive.zip这个-O参数允许指定解压时的字符编码是解决中文乱码的良药。不过要注意-O选项并非所有版本的unzip都支持比较旧的版本可能没有遇到不支持的环境就只能用Python的zipfile模块来解压配合手工指定编码。zip还有一个特性值得提一下它本身就是“打包压缩”一体的格式。也就是说zip不像tar那样需要先归档再压缩它直接把多个文件压缩进一个zip文件里。所以如果目的只是日常生活中简单共享文件zip比tar更省事。但zip也有短板——它对Unix权限位的支持没那么完善尤其是可执行权限、属主这些元数据跨环境解压后往往丢失。所以服务器上的程序部署包我还是优先用tar.gz权限保留得更好。4. 那些年踩过的坑文件打包压缩常见问题排查4.1 tar解压后权限全变了怎么办这是一个非常典型的坑。很多时候你收到一个tar.gz包解压后准备直接用结果发现文件权限不对比如脚本不能执行、目录进不去甚至文件属主成了自己的用户而不是原本的属主。究其原因是解压过程中当前用户的umask值影响了文件的权限位。解决方法是使用-p参数。之前提到过这里再展开说一下实际场景我处理一次系统迁移时把整个用户目录用tar -czf打成了包到了新机器上用普通用户解压后发现所有文件属主变成了当前用户可执行权限也没了。因为备份数据里的属主ID和属主名在新机器上不一定对得上tar作为普通用户在解压时也不能强行设置属主就只能用了当前用户的身份。最终我的解决办法是加上-p参数重新解压并用sudo来执行让tar尽可能还原原始的权限和属主信息。所以备份他人目录或者做系统级迁移时务必用sudo加-p参数来执行tar。不用怕麻烦不然一堆文件权限不对排查起来更麻烦。4.2 解压出来的路径跟想象的不一样用tar -t看一下包内文件列表是每次解压前都应该养成的习惯。但即使看了列表还是有一个坑等着你包内路径不带有顶层目录。比如有人打包时图省事直接在某个目录内部执行了tar那么压缩包里的文件可能是分散的解压出来会全部撒到你当前目录里覆盖同名文件。规避这个问题的办法有两个一是解压前先建一个专门的目录然后配合-C参数解压进去mkdir /tmp/restore tar -xzf package.tar.gz -C /tmp/restore/二是创建包时手动包一层父目录比如tar -czf package.tar.gz -C /path/to/parent project/这样解压出来会得到project/这个顶部目录所有文件都归拢在里面不会散落一地。这是我的长期习惯不管是在脚本里还是手工操作解压前都先创建目标目录既保证了路径可控又方便之后整理。4.3 增量备份该怎么做只打包新增的文件增量备份的需求在实际运维中很常见。全量备份每天做的话太占空间你只想把当天新增或改动的文件打包那么tar的-u参数可以帮上忙tar -czf archive.tar.gz -u project/-u代表update它会在归档中检查同名文件的时间戳如果当前文件比归档里的新就替换进去。但这里有个前提条件归档文件必须已经存在并且是以非压缩的形式tar格式不是tar.gz才能增量更新。因为压缩格式无法在原有基础上直接追加tar只能重新处理整个包。所以增量备份的正确玩法是先用tar -cf生成未压缩的tar包然后定期用-u去更新它最后再对tar包做一次压缩。先打包再压缩这两个动作可以分开反而是全量加增量的最佳实践。不过说实话增量备份这个功能在今天的生产环境里有点鸡肋了因为rsync在这方面的表现要出色得多。tar -u适合临时用用长期做增量备份我强烈建议改用rsync它支持按大小、时间、校验和等多种方式同步效率和可靠性都要高得多。4.4 超大文件怎么分卷和校验碰到超大文件比如一个目录压缩后还有好几十G但你的目标存储介质比如U盘单文件限制4G这时候就需要把文件分卷。Linux下用split命令split -b 4G -d -a 2 bigfile.tar.gz bigfile.part_得到的文件会是bigfile.part_00、bigfile.part_01这样每个大小4G。拿到另一台机器上之后用cat把它们合回原来的文件cat bigfile.part_* bigfile.tar.gz这个方案很实用但需要注意分卷过程本身不生成任何校验信息传输过程中如果哪个分卷损坏了拼出来的文件就会有问题。所以分卷传输文件时我一般会额外计算sha256校验值sha256sum bigfile.tar.gz把校验值记录下来传输完成后在目标机器上再算一次两相对比。不要觉得这是多余的步骤大文件传输出问题的概率远比想象的高有了校验才有安全感。5. 除了命令本身这些实用小技巧也得掌握5.1 用tar直接完成远程传输前面提到过用tar ssh管道直接传文件这个技巧我再展开讲讲。假如你在本地服务器A上想把数据目录送到远程服务器B上最直观的办法是先打包、再scp上传但这样本地要占用一份临时文件的磁盘空间而且多了两步操作。更高效的做法是一步到位tar -czf - /data/project | ssh userremote tar -xzf - -C /data/这条命令的逻辑是本地tar把数据打包并输出到标准输出ssh把那串数据通过网络送到远程服务器远程服务器上的tar再从标准输入读取并解压到指定目录。全程没有中间文件磁盘不占额外空间传输效率也很高。这个技巧我在服务器间搬迁数据时用得最多。当年迁移一批服务配置和数据几百G的内容就是靠这种流式传输逐目录搬完的。省了本地临时文件不说整个过程的进度可观测性也比scp好因为tar的输出你可以方便地用工具去监控。需要注意的是远程目录必须提前创建好ssh用户也需要有对应目录的写入权限。5.2 从损坏的压缩包里抢救数据压缩包损坏是个很尴尬的事尤其是那种没有备备份的唯一副本。如果是gzip压缩的tar包损坏可以尝试用gzip -cd加上tar的容错选项来还原gzip -cd archive.tar.gz | tar -xvf -如果tar包本身损坏还可以加--ignore-zeros参数跳过坏块有一定概率把损坏位置前后的数据都恢复出来。这个方法不是100%有效但遇到只有一份备份的场景尝试抢救总比直接放弃强。另外一个经验是重要压缩包文件一定要留备份因为压缩包本身是二进制文件一旦几个字节损坏就可能整个报废。我对重要数据的规则很朴素至少两份副本放在不同介质上并且每次大版本更新后重新校验一份新的压缩包。5.3 养成用tar -t先查看内容的习惯这点算是老生常谈但我还是要强调。每次解压之前尤其是处理来路不明的压缩包时先用tar -t看一遍内容确认里面是不是有个顶层目录有没有可疑文件路径是否合理。这个习惯花不了多少时间却能帮你避开“解压后文件散一地”“解压出个奇怪名字的目录”这些尴尬情况。而且查看内容还能帮你确认压缩包的格式。有些包虽然后缀写.tar.gz实际可能是纯tar格式或者xz格式。直接tar -xf会自动识别但如果要手动指定参数先看清楚格式就不会出错了。我现在打磨出的流程就是下载压缩包后先ls看大小是否合理再tar -t看内容结构和文件数量最后决定用哪种方式解压。5.4 利用压缩工具搭配rsync实现高效同步打包压缩不止用于备份归档在日常同步中也大有用处。比如你想把本地大量小文件快速同步到服务器上直接rsync一个个文件传输会遇到非常严重的“小文件延迟”问题每个文件都有建连和确认的开销几万个文件传下来时间非常难看。更好的思路是先本地打包压缩再传压缩包最后远程解压tar -czf - /data/project/ | ssh userremote cat /tmp/project.tar.gz tar -xzf /tmp/project.tar.gz -C /data/这样数据传输的量小了文件数量变成了一个整个过程会快很多。对于服务器之间迁移大批静态文件、图片素材这类场景这个方案几乎是效率最优解。当然如果两端都有rsync且经常要做增量更新那直接rsync是更好的选择。但如果你只是偶尔一次做整目录迁移打包压缩传输再解压的套路简单直接值得熟练应用。6. 一个完整的实战流程参考讲了不少命令和技巧我最后把一个真实的“日志归档”场景完整过一遍。假设我现在要归档某台服务器上/home/app/logs目录下的历史日志日志按天命名已积累了大半年。第一步先看一下整个目录有多大确认磁盘空间够不够。du -sh /home/app/logs ls /home/app/logs | wc -l第二步创建归档前先建好归档目录并准备好排除规则。日志里有一些临时文件、调试输出我不想打包就写排除模式。mkdir -p /data/archive tar -czf /data/archive/logs_2024.tar.gz --exclude*.tmp --excludedebug -P /home/app/logs第三步打包完成后立刻做完整性校验。比较稳妥的方式是把原始目录的文件数和大小统计出来和归档包里的对比find /home/app/logs -type f | wc -l tar -tzf /data/archive/logs_2024.tar.gz | wc -l tar -tzf /data/archive/logs_2024.tar.gz | grep -c debug || true如果两边文件数对得上体积也吻合基本可以判断归档成功。最后我做一次sha256校验sha256sum /data/archive/logs_2024.tar.gz这个流程虽然简单但每一步都有明确的目的先看空间避免写到一半磁盘爆了再排除无关文件控制归档体积然后用文件数对比做完整性校验最后用哈希值留一个完整记录。整套下来也就几分钟但相比“敲一条tar命令就走人”的做法整体的可靠性有质的提升。另外一个重要习惯是给压缩包命名时尽量带上内容和时间。logs_20241020.tar.gz比archive.tar.gz不知道清晰多少倍。等三个月后再回来看这个包不用解压就能知道里面是什么、什么时候的归档省了自己找记录的功夫。这个好习惯也能让接手的人不再一头雾水。打包压缩这块看起来入门门槛很低好像每条命令都能用两下但要真正做到把握到位、用得顺手关键还是理解“归档和压缩是两件事、选对压缩工具、保留好权限、解压前先查看、事后做校验”这几个理念。你在实战中每踩一个坑这份理解就会更深一层。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑