tar 打包下载命令手册:逐段拆解与套用模板
适用场景 :在 AutoDL / Linux 服务器上把文件夹打包成单文件,以便下载到本地
为什么要打包 :JupyterLab 等网页文件管理器不支持下载文件夹 ,只能下载单个文件
建立时间 :2026-10-15
来源实例 :
autodl-container-38ef40b880-8646dcf9一句话用途:记住一条命令模板,换文件夹名就能反复套用
目录
- [0. 一键套用模板](#0. 一键套用模板)
- [1. 原命令逐段拆解](#1. 原命令逐段拆解)
- [1.1 七个片段的含义](#1.1 七个片段的含义)
- [1.2 cf 两个字母的含义](#1.2 cf 两个字母的含义)
- [1.3 为什么执行完没有任何输出](#1.3 为什么执行完没有任何输出)
- [2. 为什么要排除 git 目录](#2. 为什么要排除 git 目录)
- [2.1 同一份数据在硬盘上存了两遍](#2.1 同一份数据在硬盘上存了两遍)
- [2.2 体积对照](#2.2 体积对照)
- [2.3 怎么验证自己有没有误打包](#2.3 怎么验证自己有没有误打包)
- [2.4 什么情况下才该保留](#2.4 什么情况下才该保留)
- [3. 为什么一律不加 z 或 J](#3. 为什么一律不加 z 或 J)
- [4. 关于 cd 的两点澄清](#4. 关于 cd 的两点澄清)
- [4.1 波浪号和斜杠的区别](#4.1 波浪号和斜杠的区别)
- [4.2 结论:不能直接换](#4.2 结论:不能直接换)
- [4.3 确实想用绝对路径怎么办](#4.3 确实想用绝对路径怎么办)
- [5. 通用套用模板](#5. 通用套用模板)
- [5.1 模板 A:先切换目录再打包](#5.1 模板 A:先切换目录再打包)
- [5.2 模板 B:用 C 参数不改当前目录](#5.2 模板 B:用 C 参数不改当前目录)
- [5.3 只打包某个子目录](#5.3 只打包某个子目录)
- [6. 常见报错排查表](#6. 常见报错排查表)
- [7. 打包后的验收清单](#7. 打包后的验收清单)
- [8. 下载中断时的分卷方案](#8. 下载中断时的分卷方案)
- [9. tar 常用参数速查](#9. tar 常用参数速查)
- [10. 速记卡](#10. 速记卡)
0. 一键套用模板
最常用形式,只需改动三处:
bash
cd <文件夹所在的目录> && tar --exclude='.git' -cf <输出名>.tar <要打包的文件夹名>
实例演进:
| 想打包什么 | 命令 |
|---|---|
| NTURain 训练集仓库(本次案例) | cd ~ && tar --exclude='.git' -cf SPAC-SupplementaryMaterials.tar SPAC-SupplementaryMaterials |
| RainMamba 代码目录 | cd ~ && tar --exclude='.git' -cf RainMamba.tar RainMamba |
| autodl-tmp 下的数据集 | cd /root/autodl-tmp && tar -cf mydata.tar mydata |
| 纯数据目录(无 git) | cd ~/data && tar -cf dataset_v2.tar dataset_v2 |
记忆口诀:
cd 到父目录 → tar -cf 输出名.tar 文件夹名 → 有 git 就加 --exclude='.git'
通用写法(连 cd 都省掉):
bash
tar --exclude-vcs -cf <输出名>.tar -C <父目录> <文件夹名>
--exclude-vcs 会自动排除 .git / .svn / .hg 等所有版本控制目录,比手写 --exclude='.git' 更省心。
1. 原命令逐段拆解
完整命令:
bash
cd ~ && tar --exclude='.git' -cf SPAC-SupplementaryMaterials.tar SPAC-SupplementaryMaterials
1.1 七个片段的含义
| # | 片段 | 含义 |
|---|---|---|
| 1 | cd ~ |
切换到当前用户家目录 。root 用户 → /root。这一句必需,因为后面两个路径都写成了相对形式 |
| 2 | && |
逻辑与:前一条命令成功(退出码 0)才执行后一条。若 cd 失败,tar 不会在错误目录里乱跑 |
| 3 | tar |
归档工具(tape archive),把多个文件/目录合并成单个文件 |
| 4 | --exclude='.git' |
排除名为 .git 的目录。这是 glob 模式 ,不含 / 时会匹配任意层级 中叫 .git 的条目。单引号是 shell 强引用,防止特殊字符被提前展开(此处无特殊字符,加引号属规范习惯) |
| 5 | -cf |
两个选项合并写:-c = create(创建归档)+ -f = file(用文件而非标准输出,必须紧跟归档名) |
| 6 | SPAC-SupplementaryMaterials.tar |
输出归档文件名(-f 的实参) |
| 7 | SPAC-SupplementaryMaterials |
要打包的源目录 (相对当前目录 ~) |
执行后的结果位置:
text
/root/SPAC-SupplementaryMaterials.tar ← 归档文件本体(604 MB)
└── SPAC-SupplementaryMaterials/ ← 归档内的路径前缀
└── Dataset_Training_Synthetic/ ← 33 个 rar
├── t1_Rain_01.rar
└── ... ×33
包内保留了目录前缀(因为源参数写的是相对目录名)。本地解开后得到完整目录结构,不会散落一地文件。
1.2 cf 两个字母的含义
bash
tar -c -f SPAC-SupplementaryMaterials.tar SPAC-SupplementaryMaterials
# ↑ ↑ ↑
# │ │ └── 归档文件名(-f 的实参,必须紧贴其后,中间不能插别的选项)
# │ └───── 写入文件而非标准输出
# └──────── 创建新归档(create)
常见误写:
| 错误写法 | 问题 |
|---|---|
tar -c SPAC-SupplementaryMaterials.tar dir/ |
缺 -f,tar 会把归档内容喷到终端屏幕上(二进制乱码刷屏) |
tar -cf dir/ SPAC-SupplementaryMaterials.tar |
参数顺序颠倒:-f 后面跟的必须是输出名,不是源目录 |
tar cf ... |
老式写法(不带 -),能跑但可读性差,建议统一用 -cf |
1.3 为什么执行完没有任何输出
因为没有加 -v (verbose)。tar 在静默模式下成功时不打印任何内容------这符合 Unix 哲学:"无消息即成功"(No news is good news)。
bash
# 想看到打包了哪些文件,加 -v:
tar -cvf SPAC-SupplementaryMaterials.tar SPAC-SupplementaryMaterials
判断成功的正确方式是看退出码,而不是看有没有输出:
bash
cd ~ && tar --exclude='.git' -cf SPAC-SupplementaryMaterials.tar SPAC-SupplementaryMaterials && echo "打包成功"
2. 为什么要排除 git 目录
2.1 同一份数据在硬盘上存了两遍
Git 的工作方式和普通文件夹不一样。以本次的稀疏检出目录为例:
text
/root/SPAC-SupplementaryMaterials/
├── Dataset_Training_Synthetic/ ← 工作区:604 MB(checkout 出来的 33 个 rar)
│ ├── t1_Rain_01.rar
│ └── ... ×33
└── .git/
└── objects/pack/*.pack ← 对象库:~603 MB(同样这 33 个 rar 的另一种存放形式)
关键在于 --filter=blob:none 这个参数的作用是"延迟下载",不是"不下载":
- clone 时:只拉 8 个对象(目录树信息),文件内容一律不拿
- 执行
git checkout时:git 才把那 603.15 MiB 的内容拉下来 - 拉下来的内容先存进
.git/objects/pack/(就是传输日志里那个 603.15 MiB) - 然后从对象库再写出一份 到工作区的
Dataset_Training_Synthetic/
→ 同一批 rar,在磁盘上占了两份。
打比方 :
.git是书店的仓库 ,工作区是书架 。你要寄给朋友的是书架上的书,但不排除.git就等于把仓库连同书架一起装箱------同一批书装两遍。
2.2 体积对照
| 写法 | tar 体积 | 下载风险 |
|---|---|---|
tar --exclude='.git' -cf ... ✅ |
604 MB | 低 |
tar -cf ...(不排除) ❌ |
~1.2 GB | 高------下载量翻倍,中途断线概率也翻倍 |
单个 1.2 GB 文件走网页下载,基本必然要重来一两次。
2.3 怎么验证自己有没有误打包
先看源目录的体积构成:
bash
du -h --max-depth=1 ~/SPAC-SupplementaryMaterials | sort -h
输出示例:
text
604M /root/SPAC-SupplementaryMaterials/Dataset_Training_Synthetic
605M /root/SPAC-SupplementaryMaterials/.git
1.2G /root/SPAC-SupplementaryMaterials
最后一行是总数,前两行各占一半。⚠️ du 的父目录会包含子目录,所以单看总数会误以为"数据有 1.2 GB",其实真正需要的只有 604 MB。
再看归档本身:
bash
ls -l ~/SPAC-SupplementaryMaterials.tar
tar -tf ~/SPAC-SupplementaryMaterials.tar | wc -l
| 观察项 | 干净(已排除 .git) | 误含 .git |
|---|---|---|
ls -l 字节数 |
≈ 604 MB | ≈ 1.2 GB |
| `tar -tf | wc -l` | 约 36 行 |
⚠️ 一个反直觉的坑
tar -tf xxx.tar | grep -c '\.rar$' 这个计数无法用来判断是否误含 .git。
原因:.git 里的文件叫 xxxx.pack、xxxx.idx,压根不含 .rar 字样------两种情况数出来都是 33 。要判断必须看 ls -l 的字节数或 tar -tf | wc -l 的行数。
2.4 什么情况下才该保留
只有一种 :你要在这台机器上继续做 git 操作 ------比如再 checkout 仓库里的其他目录(测试集、代码),或者 git pull 更新。
如果目标只是把数据带回本地,本地不需要这些 git 元数据(本地有 WinRAR 就够了)。排除还有两个附带好处:
- 包里不会夹带服务器路径、git 历史、远端地址等与研究无关的信息,交付他人时更干净
- 下载量减半
3. 为什么一律不加 z 或 J
| 写法 | 作用 | 本场景结果 |
|---|---|---|
tar -cf |
把文件夹变成单个文件 | 体积不变(604 MB → 604 MB) |
tar -czf |
打包 + gzip 压缩 | 收益 ≈ 0,白烧 CPU |
tar -cJf |
打包 + xz 压缩 | 更慢,收益依旧极小 |
原因:包内是已经压过的 rar(内含 jpg 图片),这些格式的熵值已接近极限,二次压缩只能再压掉约 0.5%,却要付出几十分钟 CPU 时间。
必须区分两件事:
| 解决的问题 | |
|---|---|
tar(不加 z) |
文件夹 → 单文件(这才是 AutoDL 下载限制的根源) |
-z / -J |
体积太大 → 体积变小(本场景不需要) |
JupyterLab 限制的是不能下载文件夹 ,不是"只能下载压缩包"。所以 tar -cf 完全够用。看到有人写 tar -czf 打 rar 包,那是无意义的。
特例:如果打包的是大量小文本文件 (如几千个 .py / .txt / .json),那
-z是真有用的,能压到 1/5 甚至更低。判断标准是内容是否已被压缩。
4. 关于 cd 的两点澄清
4.1 波浪号和斜杠的区别
| 写法 | 展开为 | 含义 |
|---|---|---|
~ |
/root(root 用户) |
家目录(home directory) |
$HOME |
/root |
与 ~ 完全等价 |
/ |
/ |
文件系统根目录(最顶层) |
. |
当前所在目录 | --- |
.. |
上一级目录 | --- |
术语澄清 :中文日常口语常把"根目录"用来指家目录(~),但在 Linux 语境里 / 才是根目录,~ 叫家目录。两者是不同层级:
text
/ ← 根目录(cd / 到这里)
├── bin/ etc/ home/ tmp/ usr/ var/ ...
└── root/ ← root 用户的家目录(cd ~ 到这里)
├── SPAC-SupplementaryMaterials/ ← 本次打包的目录在这里
└── autodl-tmp/
4.2 结论:不能直接换
cd ~ 换成 cd / 会失败:
bash
cd / && tar --exclude='.git' -cf SPAC-SupplementaryMaterials.tar SPAC-SupplementaryMaterials
# tar: SPAC-SupplementaryMaterials: Cannot stat: No such file or directory
原因:SPAC-SupplementaryMaterials 在 /root/ 下,不在 / 下。cd / 之后 tar 在当前目录(/)里找不到这个相对路径。
反证 :本次命令是从 / 提示符出发的------
text
root@...:/# cd ~ && tar --exclude='.git' -cf ...
root@...:~# ← 提示符变成 ~,说明 cd 确实切到了 /root 并成功找到目录
如果目录真在 / 下,cd ~ 反而会失败。
验证方法:
bash
ls -d /root/SPAC-SupplementaryMaterials # 存在 ✅
ls -d /SPAC-SupplementaryMaterials # 不存在 ❌
4.3 确实想用绝对路径怎么办
有两种写法,效果不同:
写法一:源也用绝对路径
bash
cd / && tar --exclude='.git' -cf /root/SPAC-SupplementaryMaterials.tar /root/SPAC-SupplementaryMaterials
能跑,但 GNU tar 会打印警告:
text
tar: Removing leading `/' from member names
因为 Tar 格式不存储绝对路径 (避免解压时覆盖系统文件)。结果是包内路径变成 root/SPAC-SupplementaryMaterials/...,本地解开后多出一层 root/ 目录,不够干净。
写法二:用 -C 参数(推荐)
bash
tar --exclude='.git' -cf ~/SPAC-SupplementaryMaterials.tar -C ~ SPAC-SupplementaryMaterials
-C ~ 让 tar 在读取文件之前 切换到 ~,效果等同于 cd ~,但归档内的路径仍然是干净的相对路径。这是脚本里最推荐的写法------不改变当前所在目录。
5. 通用套用模板
5.1 模板 A:先切换目录再打包
适合交互式终端使用(最直观):
bash
cd <文件夹所在目录> && tar --exclude='.git' -cf <输出名>.tar <文件夹名>
要点:
cd的目标是父目录,不是文件夹本身- 最后两个参数都是相对于 cd 之后目录的路径
- 输出名建议写简单点,不要带
/,否则会跑到别处
bash
# 正例
cd ~ && tar --exclude='.git' -cf RainMamba.tar RainMamba
# 反例:cd 进了文件夹本身,然后又找同名子目录 → 必然失败
cd ~/RainMamba && tar -cf RainMamba.tar RainMamba
5.2 模板 B:用 C 参数不改当前目录
适合写进脚本 / 连续打包多个目录:
bash
tar --exclude-vcs -cf <输出名>.tar -C <父目录> <文件夹名>
实例------一次打包三个目录:
bash
tar --exclude-vcs -cf /root/backup_1.tar -C /root RainMamba
tar --exclude-vcs -cf /root/backup_2.tar -C /root DRSformer
tar --exclude-vcs -cf /root/backup_3.tar -C /root/autodl-tmp mydata
注意 -C 的相对路径陷阱 :多个 -C 会累积(第二次 -C 是相对第一次的结果)。安全做法是每个 -C 都用绝对路径。
5.3 只打包某个子目录
场景 :只想把 Dataset_Training_Synthetic 带走,不要外层仓库结构。
bash
tar -cf ~/NTURain_train.tar -C ~/SPAC-SupplementaryMaterials Dataset_Training_Synthetic
解读 :-C ~/SPAC-SupplementaryMaterials 先切进仓库目录,然后打包其下的 Dataset_Training_Synthetic。得到 604 MB 的包,解开后直接就是 Dataset_Training_Synthetic/,少一层嵌套。
6. 常见报错排查表
| 报错 / 现象 | 原因 | 解决 |
|---|---|---|
Cannot stat: No such file or directory |
源目录路径不对(相对路径基于错误的当前目录) | pwd + ls 确认位置;或用绝对路径 + -C |
Removing leading '/' from member names |
用绝对路径作源参数 | 无害,但包内会多出 root/ 层级;改用 -C 更干净 |
Cowardly refusing to create an empty archive |
源写成了不存在或空的路径 | 检查拼写;确认目录非空 |
| 终端刷出大量二进制乱码 | 忘了 -f,归档内容输出到了屏幕 |
加 -f 输出名 |
| 打完包提示符没变、命令像没反应 | tar 静默模式正常行为 | 加 && echo OK 确认,或查退出码 echo $? |
| 归档体积是预期的两倍 | 没排除 .git |
加 --exclude='.git' 或 --exclude-vcs |
| 打包耗时极长、CPU 飙高 | 误加了 z / J |
去掉压缩选项 |
| 解开后多一层同名目录 | 源参数写的是目录名本身(正常) | 若想少一层,用 -C <父目录> <子目录> |
归档里出现了 ./ 开头的路径 |
用了 tar -cf x.tar . |
改用明确的目录名 |
7. 打包后的验收清单
打包完成后(服务器端):
bash
ls -lh ~/SPAC-SupplementaryMaterials.tar
tar -tf ~/SPAC-SupplementaryMaterials.tar | head -5
tar -tf ~/SPAC-SupplementaryMaterials.tar | grep -c '\.rar$'
| 检查项 | 期望值 |
|---|---|
ls -lh 体积 |
≈ 604 MB(若 1.2 GB 说明含了 .git) |
| `tar -tf | head -5` |
grep -c '\.rar$' |
33(本次数据集的 rar 总数) |
记录字节数,供下载后比对:
bash
ls -l ~/SPAC-SupplementaryMaterials.tar | awk '{print $5}'
→ 把这个数字抄下来。
下载完成后(本地端):
bash
ls -l SPAC-SupplementaryMaterials.tar
→ 字节数与服务器端完全一致才算下载成功。
⚠️ 这是本手册最重要的一条 :不要靠"能打开"判断完整性。历史教训是一次下载的文件恰好截断在整数 MiB 边界上(340,787,200 字节 = 恰好 325 MiB),看起来大小"正常",实际已损坏,WinRAR 报"不可预料的压缩文件末端"。必须对数字。
可选:用 MD5 做终极校验
bash
# 服务器端
md5sum ~/SPAC-SupplementaryMaterials.tar
# 本地端(Git Bash)
md5sum SPAC-SupplementaryMaterials.tar
# 本地端(PowerShell,输出大写,内容相同)
Get-FileHash -Algorithm MD5 ".\SPAC-SupplementaryMaterials.tar"
8. 下载中断时的分卷方案
症状:单文件走网页下载反复中断,或下完发现大小对不上。
对策:切分成多个小卷,只重下失败的那一卷。
第一步:算清楚要切几卷
text
604 MB = 575.5 MiB
200 MiB × 3 = 600 MiB > 575.5 MiB
→ 分 3 卷:part00(200M) + part01(200M) + part02(175.5M)
第二步:切分
bash
cd ~ && split -b 200M -d -a 2 SPAC-SupplementaryMaterials.tar SPAC-SupplementaryMaterials.tar.part
ls -lh ~/SPAC-SupplementaryMaterials.tar.part*
-b 200M 每卷 200 MiB | -d 用数字后缀 | -a 2 后缀两位数(00/01/02)
第三步:逐卷下载(网页下载 3 个文件,比下 1 个大文件稳)
第四步:本地合并
bash
# Git Bash
cd "本地下载目录"
cat SPAC-SupplementaryMaterials.tar.part00 SPAC-SupplementaryMaterials.tar.part01 SPAC-SupplementaryMaterials.tar.part02 > SPAC-SupplementaryMaterials.tar
⚠️ 必须按 part00 → part01 → part02 顺序写 ,不要图省事写 cat *.part*(某些排序下会错乱)。
bash
# 或 Windows CMD
copy /b part00+part01+part02 SPAC-SupplementaryMaterials.tar
第五步:校验
bash
md5sum SPAC-SupplementaryMaterials.tar # 与服务器端 md5sum 对拍
tar -tf SPAC-SupplementaryMaterials.tar | grep -c '\.rar$' # 应为 33
分卷方案的核心价值 :某一卷下载失败时只需重下该卷(200 MB),不必整体重来(604 MB)。
9. tar 常用参数速查
| 参数 | 全称 | 含义 |
|---|---|---|
-c |
create | 创建新归档 |
-f |
file | 指定归档文件名(必须紧跟文件名) |
-v |
verbose | 打印处理的文件列表 |
-t |
list | 列出归档内容(不解开) |
-x |
extract | 展开归档 |
-C |
directory | 切换目录(读取前 / 写出前) |
--exclude= |
--- | 排除匹配的条目(glob 模式) |
--exclude-vcs |
--- | 自动排除 .git / .svn / .hg / .bzr 等版本控制目录 ✅ 推荐 |
-p |
preserve | 保留权限信息 |
-z |
gzip | gzip 压缩 ⚠️ 本场景不用 |
-J |
xz | xz 压缩 ⚠️ 本场景不用 |
-r |
append | 向已有归档追加文件 |
-u |
update | 只追加比归档中更新的文件 |
必记的三组:
bash
tar -cf out.tar dir/ # 打包(最常用)
tar -tf out.tar # 查看内容(不展开)
tar -xf out.tar # 展开
10. 速记卡
日常场景 → 直接抄
bash
# ① 打包某个文件夹(排除 git,最常用)
cd ~ && tar --exclude='.git' -cf 输出名.tar 文件夹名
# ② 打包但不改变当前目录(脚本友好)
tar --exclude-vcs -cf ~/输出名.tar -C ~ 文件夹名
# ③ 只打包仓库里的某个子目录
tar -cf ~/输出名.tar -C ~/仓库名 子目录名
# ④ 查看包内容 / 体积 / 文件数
tar -tf ~/输出名.tar | head -5
ls -lh ~/输出名.tar
tar -tf ~/输出名.tar | wc -l
# ⑤ 下载前先记字节数(供本地比对)
ls -l ~/输出名.tar | awk '{print $5}'
# ⑥ 下载中断就分卷
split -b 200M -d -a 2 ~/输出名.tar ~/输出名.tar.part
四条铁律
cd到父目录,不是文件夹本身- 有
.git就加--exclude='.git'(否则体积翻倍) - 永远不加
z(rar/jpg 已压缩,白烧 CPU) - 下载后对字节数,不要靠"能打开"
three 个最容易混淆的路径
| 写法 | 实际位置 |
|---|---|
~ |
/root(家目录) |
/ |
文件系统最顶层(不是你的文件所在处) |
. |
当前目录 |
文档结束 · 2026-10-15