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

我注意到我的Ubuntu MATE 17.04系统上有一个二进制可执行文件/bin/echo

我想,那很奇怪,因为

 $ type echo echo is a shell builtin 

粗略的测试表明/bin/echo与Bash内置的echo做同样的事情:

 $ /bin/echo foo foo $ /bin/echo $USER zanna 

那么,为什么还有另一个版本的echo与Bash程序分开,为什么或何时我想使用它?

如果打开bash提示符并输入echo命令,则使用内置shell而不是运行/bin/echo 。 存在/bin/echo仍然很重要的原因是:

  1. 你并不总是使用shell。 在各种情况下,您直接运行可执行文件而不是通过shell运行。
  2. 至少在理论上,一些炮弹没有内置echo 。 实际上并不需要这样做。

要扩展#1,假设您想将名称以abc开头的所有常规文件移动到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

除了使用-exec-execdir find -execdir/bin/echo可执行文件将由其他程序调用,这些程序本身运行程序但不通过shell运行。 这发生在xargs命令( 与 find 相关 )以及许多其他上下文中,例如.desktop文件 的Exec=行 。 另一个例子是当你运行sudo echo ,如果sudo工作,这可以很方便地进行测试。

类似地,一些shell内置了printf/usr/bin/printf也存在。

您可能故意使用/bin/echo一个不太常见的原因是,如果您依赖它与shell提供的echo命令之间的差异。 man echo documents /bin/echo ; help echobash文件中回显bash内置。 echo不是非常便携,因为不同的实现 – 跨越操作系统和同一操作系统上的shell – 支持不同的选项 (例如, -e ),并且它们对反斜杠的处理也不同 。 当然,最好避免依赖这些细节,而是使用printf ,这样更便携 。

bash ,你也可以使type内置show /bin/echo – 假设/bin在你的$PATH因为它总是应该 – 通过传递-a标志 :

 $ type -a echo echo is a shell builtin echo is /bin/echo 

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 

其中有多少需要构建? [echofalseprintfpwdtesttrue不需要内置:它们不会做任何只有内置函数可以做的事情(影响或获取外部命令不可用的shell状态)。 Bash的printf至少利用了内置printf -v varprintf -v var将输出保存到变量var 。 bash中的time也很特殊:通过成为关键字,您可以在bash中计算任意命​​令列表(短划线没有等效time )。 pwd也不需要是内置的 – 任何外部命令都将inheritance当前的工作目录(它也是一个外部命令 )。 :是一个例外 – 你需要一个NOP,并且:是它。 其余的执行外部命令可以轻松执行的操作。

因此,这些内置组件中的五分之一不需要内置。 那为什么? dash *实际上解释了为什么这些是内置的(强调我的):

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

这就是它们:这些内置存在,因为它们经常使用,交互式和脚本使用,并且它们的function非常简单,shell可以完成这项工作。 所以它发生了:一些(大多数?)炮弹承担了工作。**从2.9 BSD回到sh ,你将找不到内置的echo

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


*这几乎与Almquist shell的相应联机帮助页文本完全相同,这是Debian Almquist shell的基础。

** zsh将这个想法发挥到极致:通过加载各种模块获得的命令,比如zmv , 是你认为shell甚至不需要进入的东西 。 那时,真正的问题是: 为什么你会使用bash而不是zsh,它拥有所有这些内置函数?