`set -o posix` 在 WSL2 Ubuntu 20.04 上的 Bash 5.0.17 中不起作用

`set -o posix` Not Working in Bash 5.0.17 on WSL2 Ubuntu 20.04

如标题所述,set -o posix 选项似乎在 GNU/Linux bash 5.0.17 中不起作用(我不确定它是否与 WSL2 Ubuntu 20.04 或任何东西,但要注意以防其他人在他们的机器上工作。

我可以打开和关闭它:

$ set -o |grep posix
posix        off
$ set -o posix
$ set -o |grep posix
posix        on
$ set -o posix
$ set -o |grep posix
posix        off
$ set -o posix
$ set -o |grep posix
posix        on

但是,例如,打开时我可以执行以下操作

$ set -o posix
$ set -o |grep posix
posix        on
$ type cd
cd is a shell builtin
$ cd /
$ ls
bin   dev  home  lib    lib64   lost+found  mnt  proc  run   snap  sys  usr
boot  etc  init  lib32  libx32  media       opt  root  sbin  srv   tmp  var
$ cd() { :; }
$ type cd
cd is a function
cd ()
{
    :
}
$ cd ~
$ ls
bin   dev  home  lib    lib64   lost+found  mnt  proc  run   snap  sys  usr
boot  etc  init  lib32  libx32  media       opt  root  sbin  srv   tmp  var
$ unset -f cd
$ cd ~
$ ls
Desktop  Documents  Downloads  Music  Pictures  Public  Templates  Videos

我能够覆盖所有特殊的内置函数(包括 builtintype!)。另外,我不是 root,只是在我的用户帐户中。有谁知道我做错了什么?

更新:

@Shawn、@oguzismail 和@Dan 都在下面给出了正确答案:cdregular 内置函数。我想补充一些说明,因为我认为这对像我这样的学习者很重要:

@oguzismail 正确地指向了 Classic Shell Scripting 的部分,该部分解释了 cd 是一个常规的 built-in:

For this reason, you can write a function named cd, and the shell will find your function first, since cd is a regular built-in

我的困惑来自摘要中的陈述:

Built-in commands exist either because they change the shell’s internal state and must be built-in (such as cd), or for efficiency (such as test).

在这里,cd 是一个内置函数,但正如作者之前所说,它是一个 常规 内置函数。它必须是 shell 内置的命令,因为该命令会更改 shell 的内部状态(即它会更改 shell 的 current/present 工作目录),但是它可以是 regularspecial 内置。正如@Dan 提到的,POSIX IEEE Std 1003.1-2017 标准第 2.14 节将其定义为 regular 内置函数。 (至少出于一个原因,Classic Shell Scripting 的第 7.9 节表明这样做允许程序员自定义其行为。)

请注意! (NB = Nota Bene):如果您确实选择用 user-defined 函数覆盖 cd,请在您想要实际更改目录的函数定义中使用 command cd。函数 command 跳过按 special built-ins --> functions --> regular built-ins --> external commands on $PATH 的 POSIX-defined 搜索顺序查找函数。否则,如果您在 user-defined 函数 cd 中使用 cd,您很可能会以无限递归循环结束。 (Classic Shell Scripting 也涵盖了这一点。)

这里的关键是 bash 认为 特殊内置 是什么。我必须深入研究 the source 才能找到一个列表:

/* The Posix.2 so-called `special' builtins. */
char *special_builtins[] =
{
  ":", ".", "source", "break", "continue", "eval", "exec", "exit",
  "export", "readonly", "return", "set", "shift", "times", "trap", "unset",
  (char *)NULL
};

他们也是described in the POSIX documentation as being distinct from regular built-ins

确实...

$ bash --posix
bash-4.4$ break() { :; }
bash: `break': is a special builtin
bash-4.4$ type break
break is a special shell builtin
bash-4.4$ type cd
cd is a shell builtin

请注意 typebreakcd 的不同输出,因为后者不在该列表中。

set -o posix 工作正常:

  $ set -o posix
  $ set () { :; }
bash: `set': is a special builtin

cd 不是内置的 specialbuiltintype.

也不是

“特殊内置”列表在 posix 规范中 clearly defined

“特殊内置”不同于 shell 可能会或可能不会作为内置实现的任何其他命令。