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

cai*_*fei 8 command-line symbolic-link

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

在第一次尝试中,我使用了相对路径,最后得到了一个 broken symbolic link...

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

Zan*_*nna 7

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

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
Run Code Online (Sandbox Code Playgroud)

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

zanna@toaster:~/playground/linkyland$ > sauce
zanna@toaster:~/playground/linkyland$ file target
target: symbolic link to sauce
Run Code Online (Sandbox Code Playgroud)

现在链接有效。我们只能使用基本名称(路径的最后一个元素),因为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
Run Code Online (Sandbox Code Playgroud)

该符号链接不起作用,因为这里没有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
Run Code Online (Sandbox Code Playgroud)

但是,我们也可以通过创建正确的相对路径来修复它:

~/playground/anotherplace$ rm target 
~/playground/anotherplace$ ln -s ../linkyland/sauce target
~/playground/anotherplace$ file target
target: symbolic link to ../linkyland/sauce
Run Code Online (Sandbox Code Playgroud)

所以我们需要绝对路径的想法是……完全错误的。我们需要一个正确的路径,绝对的或相对的。

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

~/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
Run Code Online (Sandbox Code Playgroud)

所以通常最好使用相对路径。但是,如果源文件的位置是不可能改变的,但是符号链接的位置可能发生变化,这将是最好使用绝对路径:

~/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
Run Code Online (Sandbox Code Playgroud)


ale*_*lex 6

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

来自ln的官方文档:

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

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

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

我的错误是假设该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 Code Online (Sandbox Code Playgroud)

检查生成的链接发现有两个链接已损坏,即没有相对标志且从其驻留目录外部创建的链接 ( /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
Run Code Online (Sandbox Code Playgroud)