Linux 软链接与硬链接
一、先分清楚两种链接
硬链接是同一个东西的不同名字,软链接是贴在墙上的地址便条。
| 软链接 | 硬链接 | |
|---|---|---|
| 命令 | ln -s 目标 链接名 | ln 目标 链接名 |
| 本质 | 独立文件,存目标路径字符串 | 同一 inode 的另一个目录项 |
| 跨文件系统 | ✅ | ❌ |
| 链接目录 | ✅ | ❌ |
| 删除原文件 | 链接断裂 | 不受影响 |
| 日常首选 | ← 90% 场景用它 | 少用 |
二、软链接
2.1 创建
ln -s <目标> <链接名>常用选项:-f(强制覆盖已有文件),-n(链接名本身是软链接且指向目录时,替换链接而非跟进目录)。
行为取决于<链接名>当前状态:
| 链接名状态 | 行为 |
|---|---|
| 不存在 | 创建链接名 → 目标 |
| 已存在,是目录 | 进到目录里面创建目标末级名 → 目标 |
| 已存在,是文件 | 报错File exists,加-f覆盖 |
# 状态1:/home/user/link 不存在 $ ln -s /home/user/project /home/user/link # → /home/user/link -> /home/user/project # 状态2:/home/user/link 已存在,是普通目录 $ ln -s /home/user/project /home/user/link # → /home/user/link/project -> /home/user/project # 链接跑到目录里面了! # 状态3:/home/user/link 已存在,是文件 $ ln -s /home/user/project /home/user/link # ln: failed to create symbolic link '/home/user/link': File exists $ ln -sf /home/user/project /home/user/link # -f 强制覆盖2.2 日常操作
# 假定 /home/user/link -> /home/user/project mv /home/user/link /home/user/newname # 改名条,不影响目标 mv /home/user/project /home/user/other # 目标被移动 → 链接断裂(ls 变红) echo "hello" >> /home/user/link/data.log # 通过链接读写 → 目标同步更新2.3 删除
# 指向文件的软链接,直接删 rm /home/user/link # 指向目录的软链接,需要 -r rm -r /home/user/link陷阱:
rm -r /home/user/link/(末尾带/)会顺着链接删掉目标目录的内容。删链接本身不要带/。
2.4 限制
- 目标被移动或删除后链接断裂(死链),不会自动修复
- 不支持 inotify 追踪目标变化
三、硬链接
3.1 创建
ln <目标> <链接名>硬链接只能链接已存在的文件,不能链接目录。
$ echo "第一行" > a.txt $ ln a.txt b.txt $ ln -f a.txt b.txt # -f 强制覆盖已有文件3.2 日常操作
$ ls -li 1234 -rw-r--r-- 2 user group 13 ... a.txt # inode=1234, 链接数=2 1234 -rw-r--r-- 2 user group 13 ... b.txt # 同一个 inode $ echo "第二行" >> b.txt # 改 b.txt $ cat a.txt # a.txt 同步变化 第一行 第二行 $ mv a.txt c.txt # 改名不影响,仍是同一个 inode3.3 删除
$ rm a.txt # 链接数 2 → 1 $ cat b.txt # b.txt 不受影响 第一行 第二行 $ rm b.txt # 链接数 → 0,数据释放3.4 限制
- 不能跨文件系统(不同分区/磁盘)
- 不能链接目录(Linux 禁止,防止环路)
- 目标必须已存在
3.5 硬链接 vs 复制
| 复制(cp) | 硬链接(ln) | |
|---|---|---|
| 数据实体 | 两份独立 | 同一份 |
| 改一个影响另一个 | 不影响 | 互相影响 |
| 磁盘占用 | 翻倍 | 几乎不额外占空间 |
四、WSL 场景速查
| 场景 | 做法 | 原因 |
|---|---|---|
| WSL 访问 Windows 文件夹 | ln -s /mnt/c/目标 ~/链接 | 软链接即可,两边同步 |
| 频繁读写小文件 | 放 WSL 原生~/,不要放/mnt/c/ | 跨 FS 性能差(9p 协议) |
| Windows 访问 WSL 文件 | 资源管理器 →\\wsl$\<发行版> | 不需要链接 |
五、速查卡
| 我想…… | 命令 |
|---|---|
| 创建软链接 | ln -s /path/to/target linkname |
| 强制覆盖已有链接 | ln -sf /path/to/target linkname |
| 替换指向目录的软链接本身 | ln -snf /path/to/target linkname |
| 删除软链接(文件) | rm linkname |
| 删除软链接(目录) | rm -r linkname(不要末尾加/) |
| 创建硬链接 | ln existing_file new_name |
| 查看链接数及 inode | ls -li |