“ln”和“ln -s”看似不一致的行为

try*_*sis 1 hard-link symlink ln

众所周知,该ln命令创建一个链接,默认为硬链接,-s选项为创建符号链接。一般语法是ln [-s] OLD NEW,其中 OLD 是您要链接到的文件, NEW 是您正在创建的新文件。不能为目录创建硬链接,因为可以在彼此内部的文件夹之间创建硬链接,我想计算机还没有资源来检查这个,而不会出现严重的减速。

创建链接时,必须写出两个文件的路径,可以是绝对路径,也可以是相对路径。您可以混合使用相对和绝对文件路径,即新文件/文件夹的相对路径和旧文件/文件夹的绝对路径。创建具有相对路径的硬链接时,两个文件的路径都相对于当前文件夹,而对于符号链接,链接到的文件/文件夹的路径相对于其父文件夹,但旧文件的路径/folder 相对于当前文件夹。为什么这是“相对”于我的问题。

例如,假设我们在 HOME 文件夹中,/home/user,也称为~,并创建 2 个文件夹,newnew2,文件file夹中的文件new。如果我们尝试ln -s new/file new2/file,结果是从~/new2/file当前不存在的链接断开~/new2/new/file。但是,如果我们改为运行ln -s ../new/file new2/file,我们会得到预期的结果,即从~/new2/file到的链接~/new/file

所以,我的问题:

为什么符号链接的旧文件/文件夹的文件路径相对于其父文件,而其他 3 个路径(硬链接旧文件、新文件、符号链接新文件/文件夹)相对于当前文件夹?

所有这些都在 Fedora 上,但我确信它适用于大多数基于 UNIX 的操作系统。

编辑E Carter Young 似乎对我的第二个问题(以及我的第一个问题,无论如何都是错误的)一针见血。似乎对于符号链接,目标还不必存在,因此系统必须使其路径相对于链接而不是当前目录。但是,为什么 shell 在您运行命令时不能解析出该路径,而不是强制用户找出路径是什么并自己输入?shell 似乎解析得很好,所以这是遗留问题的情况吗?性能问题?什么?

eyo*_*100 6

阅读您的手册页:问题 1 = 1st Form,这是因为在 linux 中所有项目都被视为文件,甚至是目录。例如,使用文本编辑器“打开”/etc/,即: nano -w /etc/ nano 会礼貌地告诉您 /etc/ 是一个目录,因为创建永无止境的符号链接在技术上是合法的。在过去,在编写边界检查之前,我可以拥有一个 FHS 系统,其中包含 2 个名为 /etc 的文件,一个是文件,一个是目录,系统知道区别

(请参阅chromos开发人员指南中的哈哈注释:

有一个文件系统循环,因为在 ~/trunk 中你会再次找到 chroot。不要想太久。如果您尝试使用 du -s ${HOME}/chromiumos/chroot/home,您可能会收到有关文件系统损坏的消息。这没什么好担心的,只是意味着您的计算机也不理解这个循环。(如果你能理解这个循环,请尝试一些更难的事情。

我敢,点击更难的东西 :) 为了防止循环,ln 需要完整路径。

问题2可以通过再次阅读手册页来回答看最后一句:

描述

   In the 1st form, create a link to TARGET with the name LINK_NAME.  In
   the 2nd form, create a link to TARGET in the current directory.  In
   the 3rd and 4th forms, create links to each TARGET in DIRECTORY.
   Create hard links by default, symbolic links with --symbolic.  By
   default, each destination (name of new link) should not already
   exist.  When creating hard links, each TARGET must exist.  Symbolic
   links can hold arbitrary text; if later resolved, a relative link is
   interpreted in relation to its parent directory.
Run Code Online (Sandbox Code Playgroud)

回复:编辑: “但是,为什么 shell 在您运行命令时不能解析出该路径,而不是强迫用户找出路径是什么并自己输入?”


考虑这个例子:应用程序 A 安装库版本 1.0.a。您构建依赖于库 A 的应用程序 X、Y、Z。应用程序 A 发现错误,更新它并将库保存为 1.0.1.2.a。由于应用程序 X、Y 和 Z 仍然使用库 1.0,如果我直接用 1.0.1.2 替换 1.0,我会损坏,但如果我象征性地将 1.0.1.2 版链接到 1.0 版,则没有任何问题,

ln -s /usr/lib64/libfoo-1.0.1.2.a /usr/lib64/libfoo-1.0.a
Run Code Online (Sandbox Code Playgroud)

和应用程序 X、Y 和 Z 也从应用到它们的库中获得新的错误修正,因为 shell 遵循从 1.0 到 1.0.1.2 的链接,但称其为 1.0。在这种情况下,您不希望 shell 假设路径,因为您增加了系统范围损坏的机会。顺便说一句,64 位系统上的 /usr/lib 链接到 /usr/lib64,以弥补我刚刚大规模给出的示例,即 32 位应用程序希望将库安装在 /usr/lib 上,而在 64 位上系统没有纯 32 位库,因此 /usr/lib 链接到 /usr/lib64,如下所示:

ln -s /usr/lib64 /usr/lib
Run Code Online (Sandbox Code Playgroud)