Some commands are provided as both builtins and external utilities. Take echo for example. On my machine (macOS) running Bash 3.2,
$ type echo echo is a shell builtin
Running man bash | less --pattern='^ *echo +[' shows:
echo [-neE] [arg ...]
But running man 1 echo shows a man page for a different implementation of echo, with a different signature:
echo [-n] [string ...]
I’m able to use -e successfully, so I must be running the builtin, and presumably that’s /bin/echo
$ which echo /bin/echo
Where does the other implementation live, and how can I distinguish between builtins and external utils in general (e.g. printf)
Update/Correction Thanks @Gilles for clarifying. And the proof is in the pudding!
$ /bin/echo -e "tabc"
-e tabc
$ echo -e "tabc"
abc
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 1
To find out whether a command is built in, run type.
$ type echo echo is a shell builtin
type is itself a builtin and knows what commands are built in. (In bash, builtins can be disabled, and type will correctly report that a command is not built in if the builtin has been disabled.) type reports whatever will be executed if you use the command name — alias, function, builtin or external command.
which is an external command that reports the location of external commands. It doesn’t know anything about aliases, functions or builtins. And it might even not report the correct external commands, depending on your setup. Just forget about which and use type instead.
I must be running the builtin, and presumably that’s
/bin/echo
No! By definition, a builtin is not an external command. The code that implements the echo builtin, like all other builtins, is in /bin/bash. /bin/echo is an external command that has the same name as the echo builtin.
When a command exists both as a builtin and as an external command, using its name calls the builtin. The precedence order for command names is alias, then function, then builtin, then external command in the directories listed in $PATH in order. If, for some reason, you want to force an external command, use its full path.
Method 2
known name (word)
The best way to find what provides a word (provided that word is a valid name for an alias, function or command) is to use the option -a to type:
$ type -a echo echo is a shell builtin echo is /bin/echo
If a function and an alias are also defined, you may get a similar list to this:
$ type -a echo
echo is aliased to `echo "A new echo"'
echo is a function
echo ()
{
printf '%sn' "A function echo" "<a href="https://getridbug.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="ecc8ac">[email protected]</a>"
}
echo is a shell builtin
echo is /bin/echo
The order in which they are printed is the priority order. In the list printed above: the alias will be executed first. If the alias is removed (unalias), the function is executed. And so on and so forth.
Example:
$ echo "test" A function echo A new echo test
Quoting usually bypass aliases:
$ echo # or "e"cho, "echo", 'e'"ch"o, and many other variations. A function echo test
Which is equal to unsetting the alias:
$ unalias echo; echo test A function echo test
The function may be erassed with unset (option -f) :
$ unset -f echo $ type -a echo echo is a shell builtin echo is /bin/echo
An alias could be turn off with enable:
$ enable -n echo $ type -a echo echo is /bin/echo
And an external (external to the shell) utility may be moved:
# mv /bin/echo /bin/echo-aside # type -a echo bash: type: echo: not found
A list of builtins
If the name of the builtin is not known, it could be listed.
In bash, there is an (maybe?) oddly named command called enable (builtin in ksh).
Calling enable with no option will print an enabled list of builtins:
$ enable enable . enable : enable [ enable alias …
There are options to print all (-a), only enabled (-p or nothing), and special (as defined by Posix) builtins (-s).
Removing the word enable and making it a one line list:
$ echo $(enable -s | cut -d" " -f2) . : break continue eval exec exit export readonly return set shift source times trap unset $ echo $(enable -p | cut -d" " -f2) . : [ alias bg bind break builtin caller cd command compgen complete compopt continue declare dirs disown echo enable eval exec exit export false fc fg getopts hash help history jobs kill let local logout mapfile popd printf pushd pwd read readarray readonly return set shift shopt source suspend test times trap true type typeset ulimit umask unalias unset wait
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0