我对符号链接和“..”在 POSIX 下如何交互的理解是否正确

我对符号链接和“..”在 POSIX 下如何交互的理解是否正确

我正在研究一个路径的数学描述(比如文件路径,但也更抽象和通用)

最棘手的定义之一是..(链接帖子中的 φ) 的行为;特别是它如何与符号链接交互。

我想检查一下我是否正确理解了 POSIX 规则。

POSIX 4.14

当进程解析现有目录条目的路径名时,应按如下所述解析整个路径名。当进程解析在解析路径名之后立即创建的目录条目的路径名时,当最后一个组件的路径前缀的所有组件都已解析时,路径名解析终止。然后,该流程负责创建最终组件。 ... 路径名中的每个文件名都位于其前一个文件指定的目录中(例如,在路径名片段 a/b 中,文件 b 位于目录 a 中)。 ...如果在路径名解析期间遇到符号链接,...系统应使用符号链接的内容为剩余路径名(如果有)添加前缀...解析的路径名应为刚刚创建的路径名的解析。如果生成的路径名不以 开头,则路径名的第一个文件名的前身将被视为包含符号链接的目录。特殊文件名点应引用其前身指定的目录。特殊文件名点-点应引用其前任目录的父目录。作为特殊情况,在根目录中,点-点可以指根目录本身。 ..

所以我的理解是..POSIX 说的是,在解析到父目录之前应该扩展符号链接。

它是否正确?

因此,对于规范化路径,符合 POSIX 标准的方式是 realpath -P 这是要求所有目录都存在(但不是最终的文件组件),并从左到右展开解析符号链接(一旦遇到),然后应用.. 也就是说,在处理路径的所有步骤中都必须读取文件系统。

我们可以将其与以下行为进行对比节点.js 的Path.normalize(或者甚至是Path.posix.normalize)——我认为这在许多编程语言中是相当正常的(Python23 os.path是相似的)。这相当于realpath -s -m也就是说,它完全忽略了某些目录可能是 simlink,或者可能不存在。 这很好,因为它根本不需要接触文件系统。

如果我们采用这种方式规范化的路径,并将其赋予一个确实接触文件系统的函数(例如fs.readFile)那么它相当于我们使用 规范化了路径realpath -L,即“在符号链接之前解析..

Bashcd也表现得好像它已经处理了它的参数,realpath -L除非你给它-P标志

我是否正确理解了 POSIX 规范及其与realpath和许多(大多数?)编程语言路径库的关系?

额外问题:-P,有人有一个编程语言/库的示例(除了使用像 之类的 shell 实用程序之外realpath),它具有符合 POSIX 标准的规范化实现吗? (我相信Python 3pathlib.Path.resolve是正确的。虽然它也将相对路径转换为绝对路径。)

答案1

您对 POSIX 规范的理解是正确的。当您从目录只是文件系统中指向其他恰好有名称的节点的节点的角度来看,这是有道理的。.和的特殊节点..指向文字节点而不是路径(字符串)。

大多数编程库路径字符串操作函数与文件系统的实际内容无关,因此它们必须简单地通过字符串操作进行规范化。这样做的优点是它们可以对不存在或无权读取的路径进行规范化。

为了以 POSIX 方式规范化路径,您需要..使用绝对路径而不是相对路径进行规范化,否则它就没有意义。符号链接路径可能会将您指向文件系统的完全不同的部分,其中相对路径不再有意义或需要另一个路径才能..到达。如果您愿意,可以使用 readlink 和一些规则来确定是否可以使用相对路径,但我认为任何路径库都没有函数可以为您解决这个问题。

答案2

... Unix 上是真实的目录条目,代表属于其父目录的真实文件(文件或目录)。

..不是用于剥离路径最后一段的路径解析关键字。为了解析 a ..,您首先需要解析包含它的目录。 Nodejs 做错了。

$ mkdir -p /tmp/foo/bar/baz
$ ln -s /tmp/foo/bar/baz /tmp/symlink
$ realpath /tmp/symlink/..
  /tmp/foo/bar
$ node -e 'console.log(path.normalize("/tmp/symlink/.."))'
  /tmp

(这些条目总是在创建目录时创建,并且它们被用作当前目录及其父目录的硬链接。它们是一些罕见的示例目录硬链接,因为系统通常不允许普通用户创建目录硬链接。

ls -ld这就是为什么每当您创建子目录时目录中的硬链接计数就会增加,以及为什么目录从硬链接计数 3 开始(它们的名称、. 和它们的_name/..)。子目录..是到当前目录的硬链接,从而增加了其硬链接计数。 )

相关内容