Eliah在回答这个问题上做得很出色,但我想评论一下“为什么echo
要从Bash程序中分离出另一个版本”。那是个错误的问题。
正确的问题是:为什么它本来是内置的,而原本可以是(并且是)完美的外部命令?
为简单起见,请看破折号中的内建函数,只有38个(bash有61个,作为比较,以的输出为准compgen -b
):
. continue getopts readonly type
: echo hash return ulimit
[ eval jobs set umask
alias exec kill shift unalias
bg exit local test unset
break export printf times wait
cd false pwd trap
command fg read true
其中有多少需要内置?[
,echo
,false
,printf
,pwd
,test
,和true
不要需要是内建的:他们没有做任何事情,只有内置可以做(影响或获得壳状态,这不是提供给外部命令)。Bash printf
至少利用了内置功能:printf -v var
将输出保存到变量中var
。time
bash中的bash也很特殊:通过作为关键字,您可以为bash中的任意命令列表计时(破折号没有time
等效项)。pwd
也不需要是内置的-任何外部命令都将继承当前的工作目录(这也是一个外部命令)。:
是一个例外-您需要一个NOP,:
就是这样。其余的执行外部命令可以轻松执行的操作。
因此,这些内建函数的五分之一不需要内建。那为什么?手册dash
页 *实际上解释了为什么这些是内置函数(强调我的):
内建
本节列出了内置命令,因为它们是内置命令
需要执行一些单独的操作无法执行的操作
处理。除了这些,还有一些其他命令可能
内置以提高效率(例如printf(1),echo(1),test(1)等)。
就是这样:这些内置函数之所以存在,是因为它们以交互方式在脚本中经常使用,并且它们的功能非常简单,因此Shell可以胜任。所以它发生:一些(?大多数)弹了在工作**回去。在sh
从2.9 BSD,你不会找到一个echo
内置。
因此,最小外壳程序完全有可能跳过实现诸如内置命令之类的命令(不过,我认为当前没有任何外壳程序可以这样做)。GNU coreutils项目不假定您要在特定的shell中运行它们,而POSIX需要这些命令。因此,coreutils仍然提供这些功能,并跳过外壳之外没有任何意义的功能。
*这几乎与Almquist shell的相应手册页文本相同,而破折号Debian Almquist shell正是基于此文本。
** zsh
将这个想法发挥到了极致:通过加载各种模块而获得的命令(例如zmv
)是您甚至认为Shell都不需要进入的东西。那时,真正的问题是:为什么要使用bash代替具有所有这些内置函数的zsh?