根据"chdir" xopen specification,使用空字符串(“”)作为参数会导致错误(enoent):
[ENOENT]
A component of path does not name an existing directory or path is an empty string.
我使用命令检查了许多不同的操作系统和shell组合;
cd ""
最终调用“chdir”系统调用,argv == 2,argv [1]指向空字符串。
结果是Linux上(而不是AIX上)只有一些ksh93(不所有版本)都会返回错误。 “/ bin / sh”总是成功但在AIX上它移动到$ HOME并且在linux cwd上没有变化
为什么会有这么多差异?
答案 0 :(得分:1)
你在这里比较苹果和梨。
您引用的xopen规范是指C函数chdir
。
我使用的两个shell(bash和zsh)有一个内部命令cd,在两个shell中都有一个
cd ''
被解释为无操作。这在手册页中有解释,例如bash:
CDPATH中的空目录名与当前目录相同,即``。''。
所以这是预期的行为。请注意,您引用的标准并没有说明shell的cd命令。
我没有检查bash和zsh的开发人员如何实际执行cd命令,但如果他们想要遵守他们自己的规范,他们必须实现它(在C中)类似于:
if(argc == 0) {
chdir(getenv("HOME"));
} else if(strlen(argv[1]) == 0) {
chdir(".");
} else {
chdir(argv[1]);
}
如果没有以这种方式完成,chdir命令的行为将取决于系统库的底层实现(是的,是否符合xopen标准), this 肯定是shell实现中的一个错误(尽管与你指的不同)。
更新:正如 CoolRaoul 在评论中正确注明的那样,我对bash联机帮助页的引用与此无关,因为它仅指CDPATH中的空元素,不是cd
命令的空参数。虽然可以合理地假设两种情况下的效果应该相同,但没有明确规定。 zsh联机帮助页也是如此。在这两个联机帮助页中,也没有明确表示cd命令调用C函数chdir
(虽然这也可以合理地假设),它们似乎也没有引用对xopen规范的任何符合性。至少对于bash和zsh,我认为我们可以放心地说cd ""
的行为是未指定的。
答案 1 :(得分:1)
检查第4节, Shell& IEEE Std 1003.1™的实用程序或Open Group Base Specification。
这包含一个单独的page for cd,其中包含:
然后cd实用程序将执行与chdir()相当的操作 用curpath作为路径参数调用的函数。如果这些行动 由于任何原因失败,cd实用程序将显示适当的 错误消息和此步骤的其余部分不得执行。
这表明在cd ""
上失败的ksh93实际上是按照规范工作的。这是我在Ubuntu 14.04上看到的,ksh版本AJM 93u+ 2012-08-01
。
答案 2 :(得分:1)
如前所述,您可以追踪cd open group page以查找行为(我的注释是要点):
<slash>
字符开头,请将 curpath 设置为操作数,然后继续执行步骤7。
<colon>
- CDPATH的分隔路径名(请参阅环境变量部分)中的第一个路径名开始,如果路径名为非空,请测试该路径名的串联是否为<slash>
个字符如果该路径名没有以<slash>
字符结尾,则目录操作数命名目录。如果pathname为null,请测试dot,<slash>
字符和操作数的串联是否为目录命名。在任何一种情况下,如果结果字符串命名现有目录,则将 curpath 设置为该字符串并继续执行步骤7.否则,使用CDPATH中的下一个路径名重复此步骤,直到测试完所有路径名。
/foo:/bar:/baz
且/foo
不存在,则cd将首先尝试/foo/
并失败此步骤。然后它会尝试/bar/
。如果/bar
作为目录存在,则会将 curpath 设置为/bar/
并继续。如果CDPATH为null,它将测试./
以查看它是否指向某个目录(通常,因为这是您的pwd
)。如果-P选项生效,请继续执行步骤10.如果 curpath 不以<slash>
字符开头,请设置 curpath 到PWD值串联形成的字符串,如果PWD的值不以<slash>
字符结尾,则为<slash>
字符, curpath 。
PWD
,因为它将是$(pwd)/
。PWD
(或可能PWD/./
同样的效果)curpath 值应按如下方式转换为规范形式,从头到尾依次考虑每个组件:
<slash>
字符。<slash>
个字符。<slash>
字符,用单个<slash>
替换多个非前导连续字符来进一步简化 curpath ,以及使用单个<slash>
替换三个或更多前导<slash>
个字符。如果由于这种规范化, curpath 变量为null,则不应采取进一步的步骤。
<slash>
)是 curpath 的初始子字符串,则应始终认为此转换是可能的。在其他情况下是否认为可能是未指定的。如果 curpath 不长于{PATH_MAX}字节或目录操作数长于{PATH_MAX}字节,则实现也可能应用此转换。
因此,本质上,标准的cd ''
命令应该cd到CDPATH
的第一个现有组件(如果已设置),否则应该cd到当前目录。如果使用cd -P ''
,它还会从路径中删除符号链接。这样,chdir
只应该用空字符串调用,如果CDPATH是非空的,但不存在任何组件,并调用cd -P ''
,因为它将通过步骤5,设置 curpath 在步骤6中为空字符串,然后从第7步跳到第10步。我没有看到任何其他方式使用空字符串调用chdir,除非执行错误步骤9太字面意思,并将 curpath 设置为最后一句后面的空字符串。 Linux上的ksh93和AIX上的/ bin / sh不符合这些规则。通过这种方式,我要小心将cd用于可能评估零长度的路径,因为正在设置的CDPATH会奇怪地影响你正在尝试做的事情(虽然CDPATH有意外和混乱的行为无论如何,不应该在大多数情况下使用。)