当前位置: 首页>>技术教程>>正文


为什么有/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 builtin而不是运行/bin/echo/bin/echo存在的重要原因是:

  1. 你并不总是使用shell。在各种情况下,您直接运行可执行文件而不是通过shell运行。

  2. 至少在理论上,一些壳没有内置的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相关)以及许多其他上下文中,例如.desktop文件的Exec=行。另一个例子是当你运行sudo echo时,如果sudo正常工作,它可以方便地进行测试。

类似地,一些壳具有内置的printf,但也存在/usr/bin/printf

您可能故意使用/bin/echo的一个不太常见的原因是,如果您依赖它与shell提供的echo命令之间的差异。 man echo文件/bin/echo; bash中的help echo记录了bash内含蛋白。 echo不是非常便携,因为不同的实现 – 跨操作系统和同一操作系统上的shell – support different options(例如,-e)和differ in their treatment of backslashes。当然,最好避免依赖这些细节,而是使用printf,即far more portable

bash中,您可以使type内置显示/bin/echo – 假设/bin$PATH中,因为它始终应该是 – 通过传递-a标志:

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

次佳解决方案

Eliah做了很好的回答,但我想评论“为什么echo的另一个版本与Bash程序分开”部分。这是错误的问题。

正确的问题是:why is this a builtin in the first place,它本来可以(并且是)一个完美的外部命令?

为简单起见,请看一下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状态)。 Bash的printf至少利用了内置函数:printf -v var将输出保存到变量var。 bash中的时间也很特殊:通过成为关键字,您可以在bash中计算任意命​​令列表(短划线没有等效时间)。 pwd也不需要是内置的 – 任何外部命令都将继承当前的工作目录(它也是一个external command)。 :是一个例外 – 你需要一个NOP,并且:是它。其余的执行外部命令可以轻松执行的操作。

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

Builtins
 This section lists the builtin commands which are builtin because they
 need to perform some operation that can't be performed by a separate
 process.  In addition to these, there are several other commands that may
 be builtin for efficiency (e.g.  printf(1), echo(1), test(1), etc).

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

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


*这几乎与the corresponding manpage text for the Almquist shell相同,后者是Debian Almquist shell的基础。

** zsh将这个想法发挥到极致:通过加载各种模块获得的命令,如zmvare things you wouldn’t think a shell need even get into。那时,真正的问题是:你为什么要使用bash而不是zsh,它拥有所有这些内置函数?

参考资料

本文由Ubuntu问答整理, 博文地址: https://ubuntuqa.com/article/1658.html,未经允许,请勿转载。