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

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

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

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

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

所以,我的问题是:

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

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

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

答案1

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

(见哈哈注释Chromiumos 开发者指南:

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

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

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

描述

   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.

回复:编辑:“但是,为什么当您运行命令时 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

应用程序 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

答案2

问题1:为什么软链接需要写出两个文件/文件夹的整个路径,而硬链接可以省略目标文件的文件名?

您也不需要指定软链接的路径或文件名,除非目标位于当前目录中。例如,如果您有一个文件~/Downloads/target_file,您可以执行以下操作:

ln `~/Downloads/target_file`

当你在 时~/,这将创建硬链接添加文件名,你也可以这样~/Downloads/target_file~/target_file

ln -s `~/Downloads/target_file`

当你在 时~/,这将创建软链接与文件名~/Downloads/target_file一起输入。~/target_file

问题2:为什么软链接的OLD文件/文件夹的文件路径是相对于其父级的,而其他3个路径(硬链接OLD、NEW文件、软链接NEW文件/文件夹)是相对于文件/文件夹的他们自己?

所有四个路径都可以是相对路径(相对于当前文件夹)以及绝对路径;唯一的标准是,如果您未指定名称或路径,则硬链接或软链接不应位于同一文件夹中。

你应该阅读ln 的手册页。已在 Ubuntu 14.04 上尝试过所有这些,但仍然通过手册页进行了确认,因此您无需担心操作系统;它不是特定于操作系统的。

答案3

创建硬链接时,在创建链接时使用源路径,因此它必须是相对于当前工作目录的路径(或绝对路径)。创建符号链接时,源路径被视为字符串;使用链接时会对其进行解释,因此它是相对于链接所在目录的。

考虑到您的示例,当前目录是/home/user.

  • 该命令ln -s new/file new2/file创建一个文本为 的符号链接new/file,并将该链接放置在位置new2/file。当程序访问该链接时,目标是/home/user/new2/new/file不存在的。
  • 该命令ln -s ../new/file new2/file创建一个文本为 的符号链接../new/file,并将该链接放置在位置new2/file。当程序访问该链接时,目标是/home/user/new2/../new/file缩写为/home/user/new/file
  • 该命令在指向相同文件(必须存在)的ln new/file new2/file位置创建一个目录条目。new2/file/home/user/new/file

在创建符号链接之前更改到目标目录通常不会那么混乱。

cd new2
ln -s ../new/file .

相关内容