为什么有 /bin/echo 以及为什么我要使用它?

为什么有 /bin/echo 以及为什么我要使用它?

/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是:

  1. 您并不总是使用 shell。在各种情况下,您都是直接运行可执行文件,而不是通过 shell。
  2. 至少理论上,有些 shell 没有echo内置命令。实际上这并不是必需的。

扩展 #1,假设你想将所有名称以 开头的常规文件移动abcsrcdest有几种方法可以做到这一点,但其中之一是:

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是,如果您依赖于它与echoshell 提供的命令之间的差异。man echo文件/bin/echohelp echobash记录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,,,,,,,并且不要falseprintfpwdtesttrue需要是内置命令:它们不会执行任何只有内置命令才能执行的操作(影响或获取外部命令无法使用的 shell 状态)。Bashprintf至少利用了内置命令的优势:printf -v var将输出保存到变量var.time在 bash 中也很特别:通过作为关键字,您可以在 bash 中定时任意命令列表(dash 没有time等效项)。pwd也不需要是内置命令 - 任何外部命令都将继承当前工作目录(并且它是外部命令也是)。:是一个例外 - 您需要一个 NOP,:是吗? 其余的执行操作是外部命令可以轻松完成的。

因此,这些内置函数中有五分之一不需要是内置函数。那么,为什么呢?手册dash* 实际上顺便解释了为什么这些是内置的(重点是我的):

内置
 本节列出了内置命令,因为它们是
 需要执行一些单独无法执行的操作
 过程。除此之外,还有其他几个命令可能
 内置效率(例如 printf(1)、echo(1)、test(1) 等)。

基本上就是这样:这些内置命令之所以存在,是因为它们在交互和脚本中使用频率很高,而且它们的功能足够简单,因此 shell 可以完成这项工作。事情就是这样:一些(大多数?)shell 承担了这项工作。** 返回sh2.9 BSD,并且您将找不到echo内置命令。

因此,最小 shell 完全可以跳过实现内置命令(尽管我认为任何当前 shell 都不会这样做)。GNU coreutils 项目不假设您将在特定 shell 中运行它们,而 POSIX 需要这些命令。因此,coreutils 无论如何都会提供这些命令,并跳过那些在 shell 之外没有任何意义的命令。


* 这几乎与Almquist shell 的相应手册页文本,Debian Almquist shell dash 就是基于此。

**zsh将这个想法发挥到了极致:通过加载各种模块获得的命令,例如zmv是你认为 shell 根本不需要进入的东西。此时,真正的问题是:为什么要使用 bash 而不是具有所有这些内置命令的 zsh?

相关内容