为什么有/ 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
仍然很重要的原因是:
- 你并不总是使用shell。 在各种情况下,您直接运行可执行文件而不是通过shell运行。
- 至少在理论上,一些炮弹没有内置
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 echo
在bash
文件中回显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
其中有多少需要构建? [
, echo
, false
, printf
, pwd
, test
和true
不需要内置:它们不会做任何只有内置函数可以做的事情(影响或获取外部命令不可用的shell状态)。 Bash的printf
至少利用了内置printf -v var
: printf -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,它拥有所有这些内置函数?