为什么“ln”命令需要绝对路径?

为什么“ln”命令需要绝对路径?

我使用命令创建了一个符号链接ln -s source target

第一次尝试时,我使用了相对路径,结果得到了broken symbolic link...

在网上搜索,我了解到我必须使用绝对路径。我感兴趣的是为什么它需要成为绝对路径而不是相对路径,这样更方便。我搜索了一下,没有找到答案。

答案1

符号链接存储您在创建时指定的路径。当文件实际上不在该路径中时,路径不起作用(符号链接已损坏)。让我们创建一个具有相对路径的符号链接...

zanna@toaster:~/playground$ mkdir linkyland anotherplace
zanna@toaster:~/playground$ cd linkyland
zanna@toaster:~/playground/linkyland$ ln -s sauce target
zanna@toaster:~/playground/linkyland$ file *
target: broken symbolic link to sauce

ln不关心源文件是否存在(所以如果你在路径中输入了错误,它不会报错)。让我们创建我们想要链接的文件,看看是否有帮助:

zanna@toaster:~/playground/linkyland$ > sauce
zanna@toaster:~/playground/linkyland$ file target
target: symbolic link to sauce

现在链接可以正常工作了。我们只能使用基本名称(路径的最后一个元素),因为sauce与位于同一目录中target,因此target可以存储路径,这些信息足以在我们需要时sauce找到它。sauce

zanna@toaster:~/playground/linkyland$ cd ../anotherplace
zanna@toaster:~/playground/anotherplace$ ln -s sauce target
zanna@toaster:~/playground/anotherplace$ file target
target: broken symbolic link to sauce

该符号链接不起作用,因为这里没有sauce。路径sauce信息不足。(从现在开始,我删除了user@host提示的一部分以便于阅读,但我显示了指示当前工作目录的部分,因为这显示了命令的工作原理。)我们可以通过使用绝对路径来创建符号链接来解决这个问题:

~/playground/anotherplace$ rm target
~/playground/anotherplace$ ls -s /home/zanna/playground/linkyland/sauce target
~/playground/anotherplace$ file target
target: symbolic link to /home/zanna/playground/linkyland/sauce

不过,我们也可以通过制作一个正确的相对路径:

~/playground/anotherplace$ rm target 
~/playground/anotherplace$ ln -s ../linkyland/sauce target
~/playground/anotherplace$ file target
target: symbolic link to ../linkyland/sauce

所以,我们需要绝对路径的想法是……错误的。我们需要一条正确的路径,无论是绝对路径还是相对路径。

如果路径发生变化,指向同一目录中文件的绝对路径的符号链接将会中断,但具有相对路径的符号链接不会中断:

~/playground/anotherplace$ cd ../linkyland
~/playground/linkyland$ ln -s /home/zanna/playground/linkyland/sauce target2
~/playground/linkyland$ cd ..
~/playground$ mv linkyland elsewhere
~/playground$ file elsewhere/target*
elsewhere/target: symbolic link to sauce
elsewhere/target2: broken symbolic link to /home/zanna/playground/linkyland/sauce

因此,通常最好使用相对路径。但是,如果源文件的位置不太可能改变,但符号链接的位置可能会改变,最好使用绝对路径:

~/playground$ cd anotherplace 
~/playground/anotherplace$ ln -s ../elsewhere/sauce target-rel
~/playground/anotherplace$ ln -s /home/zanna/playground/elsewhere/sauce target-abs
~/playground/anotherplace$ cd ..
~/playground$ mv anotherplace ..
~/playground$ cd ..
~$ file anotherplace/*
anotherplace/target-abs: symbolic link to /home/zanna/playground/elsewhere/sauce
anotherplace/target-rel: broken symbolic link to ../elsewhere/sauce

答案2

我相信我遇到了与发帖人相同的问题,这是我遇到的第一篇帖子,从那时起我意识到自己做错了什么,因此将在这里发布以防它对其他人有所帮助(在撰写本文时,这里没有其他答案或评论提到我所追求的关键信息)。

来自官方文档

当在当前目录以外的位置创建相对符号链接时,符号链接的解析将与当前目录中相同字符串的解析不同。因此,许多用户倾向于先将目录更改为将创建相对符号链接的位置,以便制表符补全或其他文件解析将找到与将放置在符号链接中的目标相同的目标。

因此,关键是要知道,你写的源/文件/路径基本上只是逐字逐句地作为文本放入链接文件中。当链接文件稍后被解释时,路径的这个文本就是你的计算机尝试导航到的位置从符号链接的目录中

我收到断开的链接,因为我运行命令的目录(并使用制表符补全)与我创建链接的目录不同. 以及 tab 补全曾是努力给我一个有效的相对路径但仅限于我当前的目录,在从任何其他目录(显然因为它是相对的)解释它的上下文中,包括我创建符号链接的其他目录,相同的相对路径都是不好的。

我的错误是假设ln命令会为我对路径进行一些巧妙的重新解释,我认为既然--relative是一个选项,那么如果没有提供该选项,ln就会将我的相对制表符完成路径解析为绝对路径,但它不是那样工作的。

经过一番尝试,我发现该--relative选项并不是将链接解释为相对路径或绝对路径,但实际上它似乎实现了我最初期望的行为!

因此,我现在明白,如果您使用ln -swithout--relative或,-r那么您为 path/to/sourcefile 编写的任何内容都将在链接文件中保持不变,并且您这里使用相对路径,但无论你输入什么路径,都会在上下文中解释从符号链接所在的目录中

但是如果你使用ln -sr那么你使用制表符补全导航到源文件从当前目录即使你没有创建符号链接在那个目录中并将ln做一些巧妙的事情来将你在命令中写入的制表符完成路径转换为从符号链接的位置解释时有效

例如:

alex@pc:/run/shm/training$ echo hello > sourcefile.txt
alex@pc:/run/shm/training$ ls
sourcefile.txt
alex@pc:/run/shm/training$ ln -s sourcefile.txt sameDirNotRelative
alex@pc:/run/shm/training$ ln -sr sourcefile.txt sameDirRelative
alex@pc:/run/shm/training$ cd ..
alex@pc:/run/shm$ ln -s training/sourcefile.txt training/oneUpNotRelative
alex@pc:/run/shm$ ln -sr training/sourcefile.txt training/oneUpRelative
alex@pc:/run/shm$ cd ..
alex@pc:/run$ ln -s shm/training/sourcefile.txt shm/training/twoUpNotRelative
alex@pc:/run$ ln -sr shm/training/sourcefile.txt shm/training/twoUpRelative
alex@pc:/run$ cd shm/training/
alex@pc:/run/shm/training$ ls -l
total 4
lrwxrwxrwx 1 alex alex 23 Jul  6 09:10 oneUpNotRelative -> training/sourcefile.txt
lrwxrwxrwx 1 alex alex 14 Jul  6 09:10 oneUpRelative -> sourcefile.txt
lrwxrwxrwx 1 alex alex 14 Jul  6 09:10 sameDirNotRelative -> sourcefile.txt
lrwxrwxrwx 1 alex alex 14 Jul  6 09:10 sameDirRelative -> sourcefile.txt
-rw-r--r-- 1 alex alex  6 Jul  6 09:08 sourcefile.txt
lrwxrwxrwx 1 alex alex 27 Jul  6 09:11 twoUpNotRelative -> shm/training/sourcefile.txt
lrwxrwxrwx 1 alex alex 14 Jul  6 09:11 twoUpRelative -> sourcefile.txt

检查结果链接发现有两个链接已损坏,其中一个链接创建时没有使用相对标志,并且位于其驻留目录之外(/run/shm/training),而另一个链接创建于同一training目录中,恰好可以工作,因为从链接的驻留目录导航时路径是有效的。

alex@pc:/run/shm/training$ file sameDirNotRelative 
sameDirNotRelative: symbolic link to sourcefile.txt
alex@pc:/run/shm/training$ file oneUpNotRelative 
oneUpNotRelative: broken symbolic link to training/sourcefile.txt
alex@pc:/run/shm/training$ file twoUpNotRelative 
twoUpNotRelative: broken symbolic link to shm/training/sourcefile.txt

答案3

符号链接不需要绝对路径。使用相对路径就可以了:

$ ls -l /usr/bin/X11
lrwxrwxrwx 1 root root 1 May 11  2017 /usr/bin/X11 -> .

瞧,这是一个到相对路径的符号链接,它工作得很好:

$ realpath /usr/bin/X11/yes
/usr/bin/yes
$ file /usr/bin/X11/yes
/usr/bin/X11/yes: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=add2c9ee02a98b5066d08d5ba2e79697880b2662, stripped

相关内容