POSIX 如何符合“/path/file/..”?

How POSIX compliant is "/path/file/.."?

我想将当前目录更改为 shell 脚本目录,包含特定的常规文件。我发现以下技巧适用于 mkshbusybox sh:

path=/path/to/regular/file
cd $path/.. 

但不在 GNU 中 Bash:

bash: cd: /path/to/regular/file/..: Not a directory

这招是不是posix不兼容,还是Bash太迂腐了?

最新版本的标准不允许这样做。 POSIX.1-2017 cd spec. 表示如果点之前的路径名部分不是目录,cd 将认为是一个错误。

来自 cd § DESCRIPTION - step 8.b:

b. For each dot-dot component, if there is a preceding component and
   it is neither root nor dot-dot, then:

    i. If the preceding component does not refer (in the context of
       pathname resolution with symbolic links followed) to a
       directory, then the cd utility shall display an appropriate
       error message and no further steps shall be taken.

当用-P选项调用cd时,省略此步骤;但是如果其中一个路径名组件命名一个既不是目录也不是目录的符号 link 的现有文件,chdir() 将失败。

此外,允许 技巧 也允许 cd 中的不一致行为。例如,当 运行 在包含名为 bar 常规文件 和名为 [=24] 的 目录 的目录中时=] 包含另一个名为 bar 目录 ,以下两个命令在 shell 中执行不同的操作,其中 cd 忽略点之前的非目录组件-dot,尽管 CDPATH 在两种情况下都包含空字符串(即 当前工作目录 )。

CDPATH= cd bar/..
CDPATH=:foo cd bar/..

下面的文字记录清楚地显示了不符合和符合的实施之间的区别。

$ tree -F
.
├── bar
└── foo/
    └── bar/

2 directories, 1 file
$ ash
$ CDPATH= cd bar/..
$ pwd
/home/oguz
$ CDPATH=:foo cd bar/..
/home/oguz/foo
$ bash
$ CDPATH= cd bar/..
bash: cd: bar/..: Not a directory
$ CDPATH=:foo cd bar/..
/home/oguz/foo

bosh, gwsh, ksh93u+m, and yash 是其他积极维护的 shell,它们实现与 bash.

相同的行为