I noticed that there is a binary executable /bin/echo
on my Ubuntu MATE 17.04 system.
I thought, that's odd, because
$ type echo
echo is a shell builtin
Cursory testing suggests that /bin/echo
does the same sort of thing as the Bash builtin echo
:
$ /bin/echo foo
foo
$ /bin/echo $USER
zanna
So, why is there another version of echo
separate from the Bash program, and why or when would I want to use it?
If you open up a
bash
prompt and type in anecho
command, that uses a shell builtin rather than running/bin/echo
. The reasons it is still important for/bin/echo
to exist are:echo
builtin. This is not actually required.To expand on #1, suppose you wanted to move all the regular files whose names started with
abc
anywhere insrc
todest
. There are several ways to do that but one of them is:But suppose, rather than just running that, you want to see every command that will be run first. Well, then you can prepend
echo
to the command, just as you might in other contexts:But
find
doesn't use a shell. That runs/bin/echo
.Besides
find
with-exec
or-execdir
, the/bin/echo
executable will be called by other programs that themselves run programs but not through a shell. This happens with thexargs
command (which is related tofind
), as well as in a number of other contexts, such as theExec=
line of a.desktop
file. Another example is when you runsudo echo
, which can be handy for testing ifsudo
is working.Similarly, some shells have a
printf
builtin but/usr/bin/printf
also exists.A less common possible reason you might deliberately use
/bin/echo
is if you were relying on the differences between it and theecho
command provided by your shell.man echo
documents/bin/echo
;help echo
inbash
documents thebash
builtin.echo
is not very portable, because different implementations--both across operating systems and across shells on the same operating system--support different options (e.g.,-e
) and differ in their treatment of backslashes. Of course, it's better to avoid relying on such details, and useprintf
instead, which is far more portable.In
bash
, you can make thetype
builtin show/bin/echo
as well--assuming/bin
is in your$PATH
as it always should be--by passing it the-a
flag:Eliah's done a great job of answering this, but I want to comment about the "why is there another version of
echo
separate from the Bash program" part. That's the wrong question.The right question is: why is this a builtin in the first place, when it could have been (and is) a perfectly fine external command?
For simplicity, take a look at the builtins in dash, a measly 38 (bash has 61, for comparison, going by the output of
compgen -b
):How many of these need to be builtins?
[
,echo
,false
,printf
,pwd
,test
, andtrue
don't need to be builtins: They don't do anything that only a builtin can do (affect or obtain shell state that's not available to external commands). Bash'sprintf
at least takes advantage of being a builtin:printf -v var
saves the output to the variablevar
.time
in bash is also special: by being a keyword, you can time arbitrary command lists in bash (dash doesn't have atime
equivalent).pwd
doesn't need to be a builtin either - any external command is going to inherit the current working directory (and it's an external command too).:
is an exception - you need a NOP, and:
is it. The rest do actions that an external command can easily do.So, a fifth of these builtins don't need to be builtins. Why, then? The
dash
manpage* actually explains in passing why these are builtins (emphasis mine):That's pretty much it: these builtins are there because they're used so often, interactively and in scripts, and their functionality is simple enough, that the shell can do the job. And so it happens: some (most?) shells took on the job.** Go back to the
sh
from 2.9 BSD, and you won't find anecho
builtin.So, it's entirely possible a minimal shell can skip implementing such commands as builtins (I don't think any current shell does, though). The GNU coreutils project doesn't assume that you're going to run them in a particular shell, and POSIX requires these commands. So, coreutils provides these anyway, and skips those which don't have any meaning outside of the shell.
* This is almost identical to the corresponding manpage text for the Almquist shell, which is what dash, the Debian Almquist shell, is based on.
**
zsh
takes this idea to the extreme: the commands you get by loading various modules, likezmv
, are things you wouldn't think a shell need even get into. At that point, the real question is: why would you use bash instead of zsh, which has all these builtins?