/bin/echo
我注意到我的 Ubuntu MATE 17.04 系统上有一个二进制可执行文件。
我觉得这很奇怪,因为
$ type echo
echo is a shell builtin
粗略测试表明,它的/bin/echo
作用与 Bash 内置命令相同echo
:
$ /bin/echo foo
foo
$ /bin/echo $USER
zanna
那么,为什么会有另一个echo
独立于 Bash 程序的版本,以及为什么或何时我要使用它?
答案1
如果你打开一个bash
提示并输入一个echo
命令,该命令使用shell 内置命令而不是运行/bin/echo
。它仍然很重要的原因/bin/echo
是:
- 您并不总是使用 shell。在各种情况下,您都是直接运行可执行文件,而不是通过 shell。
- 至少理论上,有些 shell 没有
echo
内置命令。实际上这并不是必需的。
扩展 #1,假设你想将所有名称以 开头的常规文件移动abc
到src
。dest
有几种方法可以做到这一点,但其中之一是:
find src -name 'abc*' -type f -exec mv -nv {} dest/ \;
但是假设,您不只是运行该命令,还想查看将首先运行的每个命令。那么,您可以将命令添加echo
到命令前面,就像在其他情况下一样:
find src -name 'abc*' -type f -exec echo mv -nv {} dest/ \;
但是find
不使用 shell。它运行/bin/echo
。
除了find
和-exec
或者-execdir
,/bin/echo
可执行文件将被其他程序调用,这些程序本身运行程序但不通过 shell。这发生与xargs
命令(相关的) find
,以及许多其他语境,例如线Exec=
的一份.desktop
文件. 另一个例子是当你运行 时sudo echo
,它可以方便地测试是否sudo
正常工作。
类似地,一些 shell 有printf
内置的,但/usr/bin/printf
也存在。
您可能故意使用的一个不太常见的原因/bin/echo
是,如果您依赖于它与echo
shell 提供的命令之间的差异。man echo
文件/bin/echo
;help echo
在 bash
记录bash
内置命令。可移植性echo
不是很好,因为不同的实现——跨操作系统和跨同一操作系统上的 shell——支持不同的选项(例如,-e
)和对反斜杠的处理有所不同当然,最好避免依赖这些细节,而是使用printf
相反,更加便携。
在 中,您也bash
可以让type
内置显示- 假设在您的/bin/echo
/bin
$PATH
一如既往——-a
将旗帜传递给它:
$ type -a echo
echo is a shell builtin
echo is /bin/echo
答案2
Eliah 很好地回答了这个问题,但我想评论一下“为什么有另一个echo
独立于 Bash 程序的版本”部分。这是个错误的问题。
正确的问题是:为什么这是一个内置函数,而它本来可以是(而且是)一个非常好的外部命令?
为了简单起见,看一下 dash 中的内置命令,只有 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
需要是内置命令:它们不会执行任何只有内置命令才能执行的操作(影响或获取外部命令无法使用的 shell 状态)。Bashprintf
至少利用了内置命令的优势:printf -v var
将输出保存到变量var
.time
在 bash 中也很特别:通过作为关键字,您可以在 bash 中定时任意命令列表(dash 没有time
等效项)。pwd
也不需要是内置命令 - 任何外部命令都将继承当前工作目录(并且它是外部命令也是)。:
是一个例外 - 您需要一个 NOP,:
是吗? 其余的执行操作是外部命令可以轻松完成的。
因此,这些内置函数中有五分之一不需要是内置函数。那么,为什么呢?手册dash
页* 实际上顺便解释了为什么这些是内置的(重点是我的):
内置 本节列出了内置命令,因为它们是 需要执行一些单独无法执行的操作 过程。除此之外,还有其他几个命令可能 内置效率(例如 printf(1)、echo(1)、test(1) 等)。
基本上就是这样:这些内置命令之所以存在,是因为它们在交互和脚本中使用频率很高,而且它们的功能足够简单,因此 shell 可以完成这项工作。事情就是这样:一些(大多数?)shell 承担了这项工作。** 返回这sh
从2.9 BSD,并且您将找不到echo
内置命令。
因此,最小 shell 完全可以跳过实现内置命令(尽管我认为任何当前 shell 都不会这样做)。GNU coreutils 项目不假设您将在特定 shell 中运行它们,而 POSIX 需要这些命令。因此,coreutils 无论如何都会提供这些命令,并跳过那些在 shell 之外没有任何意义的命令。
* 这几乎与Almquist shell 的相应手册页文本,Debian Almquist shell dash 就是基于此。
**zsh
将这个想法发挥到了极致:通过加载各种模块获得的命令,例如zmv
,是你认为 shell 根本不需要进入的东西。此时,真正的问题是:为什么要使用 bash 而不是具有所有这些内置命令的 zsh?