我对符号链接的基本理解是它是一个特殊文件,一个包含另一个文件的字符串路径的文件。内核的 VFS 抽象了很多内容,但是有什么原因导致符号链接似乎无法编辑吗?
换句话说:我可以编辑符号链接吗?如果没有,为什么不呢?
我确实明白有多种方法替换符号链接(答案部分中目前有两种替代方案),但获得关于为什么替换似乎是处理符号链接的唯一方法的解释会很有趣。为什么你不能改变它们指向的位置?
答案1
鉴于这-f
只是进行无声替换,您可以进行原子替换mv -T
(-T 即使 /loc.../link 是一个目录也可以工作):
ln -s /location/to/link linkname
# ...
ln -s /location/to/link2 newlink
mv -T newlink linkname
linkname
在整个过程中都可以访问。
答案2
如果通过编辑,您的意思是更改它指向的文件,那么您可以:
$ ln -s .bashrc test
$ ls -al test
lrwxrwxrwx 1 pascal pascal 7 2009-09-23 17:12 test -> .bashrc
$ ln -s .profile test
ln: creating symbolic link `test': File exists
$ ln -s -f .profile test
$ ls -al test
lrwxrwxrwx 1 pascal pascal 8 2009-09-23 17:12 test -> .profile
参数-f
( --force
) 当传递给 ln 时会导致它调用unlink()
之前的系统调用symlink()
摘自以下内容堆栈溢出答案。
答案3
符号链接需要以原子方式修改。如果你写到一半,它们就不会起作用。符号链接的内容非常小(Linux 上最多 4095 个字符:文件路径的最大长度),因此在内核级别编辑部分符号链接没有什么意义。因此,内核不提供任何接口来编辑符号链接,只提供一个用于创建新符号链接的接口,即系统symlink
调用(加上用于删除任何文件的通用接口unlink
)。
系统symlink
调用仅创建一个新的符号链接,它不会删除任何现有文件。这很烦人,但与创建文件的其他系统调用一致,例如open
(可以创建新文件或截断现有文件,但不能用新创建的文件替换现有文件)和mkdir
.
在外壳中,如你发现了,虽然您无法使用该ln
命令自动替换符号链接(ln -sf
取消链接前一个文件,然后创建符号链接),但您可以通过首先在临时名称下创建符号链接,然后将其移动到位来实现。
tmp=$(TMPDIR=$(dirname -- "$link") mktemp)
ln -sf -- "$target" "$tmp"
mv -f "$tmp" "$link"
答案4
假设 linkname 作为完成(过去)的结果而存在:
ln -s /the/path/to/a/file linkname
然后,可以通过三种方式更改符号链接:
强制使用 ln
-f
,甚至用于目录-n
(inode 可以被重用):ln -sfn /some/new/path linkname
删除符号链接并创建一个新符号链接(即使对于目录):
rm linkname; ln -s /some/new/path linkname
创建一个新的符号链接,然后
mv
它(即使对于目录也是原子更改):ln -s /some/new/path newlinkname mv -fT newlinkname linkname # linkname remains after the command