`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
我能够覆盖所有特殊的内置函数(包括 builtin
和 type
!)。另外,我不是 root,只是在我的用户帐户中。有谁知道我做错了什么?
更新:
@Shawn、@oguzismail 和@Dan 都在下面给出了正确答案:cd
是 regular 内置函数。我想补充一些说明,因为我认为这对像我这样的学习者很重要:
@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
- 第 7.9 节(Kindle 版第 261 页)
我的困惑来自摘要中的陈述:
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).
- (第 7 节总结,Kindle 版第 264 页)
在这里,cd
是一个内置函数,但正如作者之前所说,它是一个 常规 内置函数。它必须是 shell 内置的命令,因为该命令会更改 shell 的内部状态(即它会更改 shell 的 current/present 工作目录),但是它可以是 regular 或 special 内置。正如@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
请注意 type
对 break
和 cd
的不同输出,因为后者不在该列表中。
set -o posix
工作正常:
$ set -o posix
$ set () { :; }
bash: `set': is a special builtin
cd
不是内置的 special,builtin
或 type
.
也不是
“特殊内置”列表在 posix 规范中 clearly defined。
“特殊内置”不同于 shell 可能会或可能不会作为内置实现的任何其他命令。
如标题所述,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
我能够覆盖所有特殊的内置函数(包括 builtin
和 type
!)。另外,我不是 root,只是在我的用户帐户中。有谁知道我做错了什么?
更新:
@Shawn、@oguzismail 和@Dan 都在下面给出了正确答案:cd
是 regular 内置函数。我想补充一些说明,因为我认为这对像我这样的学习者很重要:
@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
- 第 7.9 节(Kindle 版第 261 页)
我的困惑来自摘要中的陈述:
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).
- (第 7 节总结,Kindle 版第 264 页)
在这里,cd
是一个内置函数,但正如作者之前所说,它是一个 常规 内置函数。它必须是 shell 内置的命令,因为该命令会更改 shell 的内部状态(即它会更改 shell 的 current/present 工作目录),但是它可以是 regular 或 special 内置。正如@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
请注意 type
对 break
和 cd
的不同输出,因为后者不在该列表中。
set -o posix
工作正常:
$ set -o posix
$ set () { :; }
bash: `set': is a special builtin
cd
不是内置的 special,builtin
或 type
.
“特殊内置”列表在 posix 规范中 clearly defined。
“特殊内置”不同于 shell 可能会或可能不会作为内置实现的任何其他命令。