第14章:链接文件
第十四章:链接文件
14.1 什么是链接?链接的作用
想象一下这样的场景:你的书架上有一本超级重要的书《Linux入门到精通》。你把它放在了"技术书籍"区,但你想在"床头"也能随时看到它。
你会怎么做?
- 选项1:买两本(浪费钱!)
- 选项2:把书拆成两半(出版社要追杀你!)
- 选项3:做个标签/索引,指向书架上的那本书!✅
在 Linux 里,这个"标签/索引"就是链接!
链接是什么?
链接(Link)是文件的"快捷方式"或"别名"。它让你可以用多个名字访问同一个文件!
graph LR
A["书名:Linux入门"] --> B["书架位置:A区"]
A --> C["快捷标签:床头书架"]
A --> D["另一个标签:办公室"]
B --> E["实际的书"]
C --> E
D --> E链接解决了什么问题?
| 问题 | 没有链接 | 有链接 |
|---|
| 同一文件多处使用 | 复制多份,占用空间 | 多个名字,一份文件 |
| 文件改名/移动 | 所有引用都要改 | 改一处,其他自动生效 |
| 程序找库 | 必须知道库的真实路径 | 可以链接到任何位置 |
14.2 硬链接:同一个 inode 的多个文件名
硬链接是 Linux 里最"直接"的链接方式——多个文件名,指向同一个 inode(数据存储位置)!
简单理解:一个文件(一个 inode、一份"身份证"),可以有多个名字。硬链接就是给同一份数据起了一个新的文件名。
14.2.1 创建硬链接:ln 源 目标
1
2
3
4
5
6
7
8
9
10
11
12
| # 创建硬链接
# 语法:ln 源文件 目标链接名
ln original.txt hardlink.txt
# 查看:
ls -li original.txt hardlink.txt
# 输出:
# 131079 -rw-r--r-- 2 user user 123 Jan 15 10:30 original.txt
# 131079 -rw-r--r-- 2 user user 123 Jan 15 10:35 hardlink.txt
# ↑ 注意:两个文件的 inode 相同(131079)!
# Links 那列都是 2(表示有2个硬链接指向这个 inode)
|
14.2.2 特点:同一分区,不能跨文件系统
硬链接虽然好用,但有严格的限制:
1
2
3
4
5
6
7
8
| # 限制1:不能跨文件系统
# /home 和 /data 可能是不同的分区
ln /home/user/file.txt /data/file_hardlink.txt
# ln: failed to create hard link '/data/file_hardlink.txt': Invalid cross-device link
# 限制2:不能链接目录
ln /home/user /home/user_hardlink
# ln: /home/user: hard link not allowed for directory
|
graph TD
A["硬链接限制"] --> B["必须同一分区"]
A --> C["不能跨文件系统"]
A --> D["不能链接目录"]
A --> E["不能链接不存在的文件"]
F["为什么?"] --> G["inode 编号只在同一分区有效"]
G --> H["目录的硬链接会破坏树结构"]硬链接的工作原理
1
2
3
4
5
6
7
8
9
10
11
| # inode 的链接计数(Links)决定了文件数据是否会被释放
# 只有当 Links = 0 时,文件数据才会被真正删除(磁盘空间回收)
# 示例:
touch original.txt # Links = 1
ln original.txt link1.txt # Links = 2
ln link1.txt link2.txt # Links = 3
rm original.txt # Links = 2,文件数据还在!
rm link1.txt # Links = 1,文件数据还在!
rm link2.txt # Links = 0,文件数据被删除,磁盘空间回收!
|
想象一下:每个 inode 就像一个公寓,Links 就像公寓的门牌号。删除硬链接只是"摘掉一个门牌号",只有当所有门牌号都没了,公寓才会被清空!
⚠️ 重要提示:硬链接创建后,所有链接都是"平等"的——没有"原文件"和"链接"的区别!它们都是指向同一份数据的文件名,删除任何一个都不影响其他链接。
14.3 软链接(符号链接):快捷方式
软链接(Symbolic Link)也叫符号链接,它更像是 Windows 的"快捷方式"——它存储的是目标文件的路径,而不是 inode!
软链接是一个"指针",指向另一个文件/目录!
14.3.1 创建软链接:ln -s 源 目标
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| # 创建软链接
# 语法:ln -s 源文件 目标链接名
ln -s original.txt symlink.txt
# 查看:
ls -li original.txt symlink.txt
# 输出:
# 131079 -rw-r--r-- 1 user user 123 Jan 15 10:30 original.txt
# 131080 lrwxrwxrwx 1 user user 12 Jan 15 10:40 symlink.txt -> original.txt
# ↑ 注意:
# 1. inode 不同(131079 vs 131080)
# 2. 文件大小是 12(因为存的是路径 "original.txt")
# 3. 类型是 l(软链接)
# 4. -> 箭头显示指向的目标
|
14.3.2 特点:可跨分区,可链接目录
软链接几乎没有限制!
1
2
3
4
5
6
7
8
9
10
11
| # 可以跨文件系统
ln -s /home/user/file.txt /data/file_link.txt
# 成功!
# 可以链接目录
ln -s /home/user/projects /home/user/projects_link
# 成功!
# 可以链接不存在的文件(软链接会变成"断链")
ln -s /nonexistent.txt dangling_link.txt
# 创建成功,但链接是断的
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
| # 检查软链接是否有效
# 1. ls -l 显示的颜色不同(红色通常表示断链)
ls -l dangling_link.txt
# lrwxrwxrwx 1 user user 12 Jan 15 10:40 dangling_link.txt -> /nonexistent.txt
# (红色,表示断链)
# 2. 用 file 或 readlink 查看它到底指向哪里
file symlink.txt
# symlink.txt: symbolic link to original.txt
readlink symlink.txt
# original.txt
# 想看到"解引用后"的最终真实路径,用 -f(注意:对断链也会尽力拼出路径)
readlink -f symlink.txt
# /home/user/original.txt
# 3. 读取链接会失败
cat dangling_link.txt
# cat: dangling_link.txt: No such file or directory
|
graph TD
A["软链接 vs 硬链接"] --> B["软链接"]
A --> C["硬链接"]
B --> D["存储文件路径"]
B --> E["inode 不同"]
B --> F["可跨文件系统"]
B --> G["可链接目录"]
B --> H["可链接不存在的文件"]
B --> I["删除源文件会断链"]
C --> J["存储 inode"]
C --> K["inode 相同"]
C --> L["不可跨文件系统"]
C --> M["不可链接目录"]
C --> N["必须链接存在的文件"]
C --> O["删除源文件不影响其他链接"]
14.4 硬链接 vs 软链接:区别与应用场景
让我们来一个全面的对比!
14.4.1 硬链接:文件备份
硬链接最适合的场景:同分区内的文件共享!
重要提示:硬链接不是真正的备份!因为修改任何一个硬链接,所有硬链接的内容都会一起变!它们本质上是"同一个文件"的不同名字。
那硬链接有什么用?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| # 场景1:同一个分区内,多个位置需要访问同一份数据
# 比如:一份很大的只读数据集,多个分析脚本都要读它
ln /data/dataset_2026.csv /opt/analysis/dataset_2026.csv
# 两个路径,物理上只有一份数据,不额外占用磁盘空间
# ⚠️ 但如果你通过其中一个名字"写入/修改",另一个名字看到的内容会同步变化——
# 所以硬链接只适合"共享只读数据",绝不能当备份用!
# 场景2:协作开发
# 两个人在同一个项目里工作,需要访问同一份代码
ln /shared/project_main.c /home/alice/project_main.c
ln /shared/project_main.c /home/bob/project_main.c
# 三个文件名,同一份代码!
# 场景3:版本控制系统的"内部原理"
# 比如 git clone --local(同一台机器上克隆本地仓库)时,
# Git 会用硬链接共享对象文件,既快又省空间(后续写入时会自动断开共享)
|
硬链接的"坑":修改任何一个硬链接,所有硬链接都会变!因为它们本质上是同一个文件!
14.4.2 软链接:软件版本管理
软链接最适合的场景:软件版本管理!
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| # 场景:你安装了多个 Python 版本
# /usr/bin/python3.8
# /usr/bin/python3.9
# /usr/bin/python3.10
# 你想让 python 总是指向最新的版本
sudo ln -s /usr/bin/python3.10 /usr/bin/python
# ↑ 源 ↑ 链接名
# 升级时:
# 1. 安装新版本
# 2. 改一下链接
sudo ln -sf /usr/bin/python3.11 /usr/bin/python
# ↑ -f 强制覆盖原来的链接
|
软链接是"软件版本管理神器"!一个链接,多个版本,切换自如!
graph LR
A["/usr/bin/python<br/>(软链接)"] --> B["指向"]
B --> C["python3.10<br/>(实际程序)"]
A -.-> D["升级时"]
D -.-> E["指向 python3.11"]
F["python3.9"] --- G["python3.10"]
G --> C
C --> H["python3.11"]
style C fill:#ff9999
style H fill:#99ff99上面这张图想表达的核心只有一句话:软链接本身只是一行"路径文本",它可以随时被改写成指向另一个版本;而 python3.9、python3.10、python3.11 这些真实文件彼此独立、谁也不指向谁。
14.5 ln 创建链接
ln = link,创建链接!
14.5.1 ln 源 目标:硬链接
1
2
3
4
5
6
7
| # 创建硬链接
ln original.txt hardlink.txt
# 验证
ls -li original.txt hardlink.txt
# 131079 -rw-r--r-- 2 user user 123 Jan 15 10:30 original.txt
# 131079 -rw-r--r-- 2 user user 123 Jan 15 10:35 hardlink.txt
|
14.5.2 ln -s 源 目标:软链接
1
2
3
4
5
6
7
| # 创建软链接
ln -s target.txt link.txt
# 验证
ls -li target.txt link.txt
# 131079 -rw-r--r-- 1 user user 123 Jan 15 10:30 target.txt
# 131080 lrwxrwxrwx 1 user user 11 Jan 15 10:40 link.txt -> target.txt
|
14.5.3 ln -sf:强制覆盖
1
2
3
4
5
6
7
8
| # -s 创建软链接
# -f 强制覆盖已存在的链接
# 如果 link.txt 已经存在
ln -sf new_target.txt link.txt
# 原来的 link.txt -> old_target.txt
# 变成了 link.txt -> new_target.txt
|
完整选项说明
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| # ln 常用选项:
# -s, --symbolic # 创建软链接(符号链接)
# -f, --force # 强制覆盖已存在的链接
# -n, --no-dereference # 如果目标是软链接,不follow它
# -v, --verbose # 显示详细过程
# 示例:
ln -sv /path/to/target link_name
# 查看链接指向
readlink link_name
# /path/to/target
# 查看链接信息
file link_name
# link_name: symbolic link to /path/to/target
|
14.6 硬链接与软链接全面对比
先把这一章的核心知识做个总览。
核心知识点:
链接是文件的"快捷方式"或"别名",让一个文件可以用多个名字访问。
硬链接:
- 多个文件名指向同一个 inode
- inode 的链接计数(Links)记录有多少个文件名
- 限制:不能跨文件系统、不能链接目录、必须链接存在的文件
- 特点:删除一个硬链接,只要还有 Links > 0,文件就不会消失
- 用途:适合同一文件需要多个"入口"的场景
软链接(符号链接):
- 存储的是目标文件的路径(类似 Windows 快捷方式)
- 没有硬链接的限制:可跨文件系统、可链接目录、可链接不存在的文件
- 缺点:删除源文件后,软链接会变成"断链"
- 用途:软件版本管理、创建路径别名、解决路径深度问题
ln 命令:
ln 源 目标 → 创建硬链接ln -s 源 目标 → 创建软链接ln -sf → 强制覆盖
硬链接 vs 软链接对比:
| 特性 | 硬链接 | 软链接 |
|---|
| 本质 | 指向同一 inode | 存储目标路径 |
| inode | 相同 | 不同 |
| 跨文件系统 | ❌ 不行 | ✅ 可以 |
| 链接目录 | ❌ 不行 | ✅ 可以 |
| 链接不存在文件 | ❌ 不行 | ✅ 可以 |
| 删除源文件 | 不影响 | 变成断链 |
| 占用空间 | 不占额外空间 | 几乎为0 |
| 性能 | 稍快 | 稍慢(多一次寻址) |
实用场景:
1
2
3
4
5
6
7
8
9
10
11
| # 1. 创建常用目录的快捷方式
ln -s /var/www/html mywebsite
# 2. 管理多个软件版本
ln -sf /opt/python-3.11.0/bin/python /usr/bin/python
# 3. 解决长路径问题
ln -s /home/user/documents/projects/linux/kernel/source /home/user/kernel
# 4. 快速访问网络存储
ln -s /mnt/nas-server/documents ~/documents
|
14.7 三个必须知道的软链接"坑"
14.7.1 相对路径是相对于"链接所在目录"解析的
这是软链接最经典的错误来源。软链接里存的路径是相对于链接自己所在的目录去解析的,而不是相对于你敲命令时所在的目录:
1
2
3
4
5
6
7
8
9
10
| # 假设当前目录是 /home/user
ln -s documents/report.txt /tmp/report_link
# 链接内容就是 "documents/report.txt"(相对路径)
readlink /tmp/report_link
# documents/report.txt
# 但 /tmp 下并没有 documents/ 目录 → 链接是断的!
cat /tmp/report_link
# cat: /tmp/report_link: No such file or directory
|
两种解决办法:
1
2
3
4
5
6
7
| # 办法一:源用绝对路径(最不容易出错)
ln -s /home/user/documents/report.txt /tmp/report_link
# 办法二:让 ln 自己算出正确的相对路径(GNU coreutils 的 -r = --relative)
ln -sr documents/report.txt /tmp/report_link
readlink /tmp/report_link
# ../home/user/documents/report.txt
|
什么时候故意用相对路径?打包/迁移场景。比如把整个项目目录(含链接)拷到另一台机器,相对链接只要内部结构不变就依然有效,绝对链接往往会断掉。
14.7.2 目标已经是个目录时,ln -s 会把链接放进目录里
1
2
3
4
| # 你想创建 /opt/app -> /srv/app-current,但 /opt/app 已经是个目录了
ln -s /srv/app-current /opt/app
# 结果不是"替换",而是在里面多了一个链接:
# /opt/app/app-current -> /srv/app-current
|
这时要用 -T(把目标当成普通文件处理)或 -n(目标本身是链接时不跟随):
1
| ln -sfn /srv/app-current /opt/app # 推荐写法:强制 + 不跟随目录/链接
|
14.7.3 删除链接本身永远不会删除源文件
1
| rm link.txt # 只删掉链接(硬链接会减少一个链接计数)
|
但真正危险的是带通配符的写法:
1
2
3
4
5
6
| # 假设 /srv/app-link 是指向 /srv/app-v2 的软链接
rm -rf /srv/app-link/* # ❌ 通配符由 shell 展开,会"穿透"链接,
# 删掉的是 /srv/app-v2 里的真实文件!
# 想删链接本身,就直接删链接(不加斜杠、不加通配符)
rm /srv/app-link # ✅ 只删掉这一个链接文件
|
一句话记住:删软链接不要加斜杠或 *;执行 rm -rf 之前,先 ls -l 看一眼这个路径到底是不是链接。
本章小结
本章我们学习了 Linux 中的链接文件,重点记住这几条:
- 硬链接是"同一份数据的另一个名字"(共享 inode),不能跨分区、不能链接目录,适合同分区内共享只读数据
- 软链接存的是"目标路径",能跨分区、能链接目录,适合做版本切换和路径别名;源文件没了就变"断链"
ln 源 目标 建硬链接,ln -s 源 目标 建软链接,ln -sfn 是覆盖软链接的推荐写法- 软链接的相对路径是"相对链接自身所在目录"解析的,拿不准就用绝对路径
- 改名要看清楚是"文件"还是"链接":
du、rsync、tar、find -L 对链接的处理方式都不一样,别想当然
恭喜你完成了 Linux 基础教程第11-14章!🎉
你已经学会了:
- 文件系统基础与各种文件系统类型
- Linux 目录结构详解
- 磁盘管理(分区、格式化、挂载)
- 链接文件(硬链接与软链接)
继续加油,Linux 大神之路,从这里开始!🚀