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

KAc*_*ion 10 bash posix cd sh ash

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

path=/path/to/regular/file
cd $path/.. 
Run Code Online (Sandbox Code Playgroud)

但不是在 GNU Bash 中:

bash: cd: /path/to/regular/file/..: Not a directory
Run Code Online (Sandbox Code Playgroud)

这个技巧不兼容posix,还是Bash太迂腐?

ogu*_*ail 8

最新版本的标准不允许这样做。POSIX.1-2017cd规范。表示如果 dot-dot 之前的路径名组件不是目录,cd则应视为错误。

cd§描述- 步骤 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.
Run Code Online (Sandbox Code Playgroud)

cd与调用-P选项,省略此步骤; 但是chdir()如果路径名组件之一命名了既不是目录也不是指向目录的符号链接的现有文件,则会失败。

此外,允许该技巧还允许cd. 例如,当在包含的目录运行常规文件命名bar目录命名foo包含另一个目录命名bar,以下两个命令在一个外壳做不同的事情cd忽略了一个点-点之前的非目录部分,尽管CDPATH包含空两种情况下的字符串(即当前工作目录)。

CDPATH= cd bar/..
Run Code Online (Sandbox Code Playgroud)
CDPATH=:foo cd bar/..
Run Code Online (Sandbox Code Playgroud)

下面的成绩单清楚地显示了不符合和符合要求的实现之间的差异。

CDPATH= cd bar/..
Run Code Online (Sandbox Code Playgroud)
CDPATH=:foo cd bar/..
Run Code Online (Sandbox Code Playgroud)
$ tree -F
.
??? bar
??? foo/
    ??? bar/

2 directories, 1 file
Run Code Online (Sandbox Code Playgroud)

炉腹gwshksh93u +米,和佳日是实现相同的行为的bash其它积极维护壳。