22

So there I was. Trying to append to $PATH. Uh oh! I accidentally unset $PATH! For whatever reason I ran

$ ls
bash: ls: command not found

To be expected. Then I ran

$ echo $PATH
$PATH:/home/jon/.local/bin

Is echo some sort of special case? Why isn't it on $PATH? Is it built in to bash?

2
  • 12
    Welcome to Ask Ubuntu! “I accidentally unset $PATH!” Not really, you seem to have set it to a not wanted value. Since your PATH now contains $PATH literally, you must have used single quotes (') instead of double quotes ("): export PATH='$PATH:/home/jon/.local/bin', haven’t you? – Melebius Feb 5 '20 at 11:15
62

echo is a bash builtin. It does not use the $PATH to find the echo program, instead bash has it's own version of echo which is used instead of the echo program located in your $PATH

read more here: Bash Builtins (Bash Reference Manual)

2
  • 2
    There's also /bin/echo, which would have vanished when OP unset $PATH – waltinator Feb 5 '20 at 3:56
  • 13
    @waltinator except, if you call it as /bin/echo it would still work regardless of PATH, and if you call it as echo, you get the builtin and not /bin/echo :) – hobbs Feb 6 '20 at 4:39
25

In addition to what Minijack mentioned, you can check what a command is by using the type builtin.

$ type echo
echo is a shell builtin

On the other hand, which can be used to check for executables specifically. Once you unset $PATH, you'll get something like

$ which echo
/usr/bin/which: no echo in ((null))

Whereas with your path set you get

/usr/bin/echo

You can check man builtins for list and desription of various builtins. For example, [ and test are also builtins.

EDIT: which works for me even without PATH because of an alias that uses an absolute path

7
  • 7
    Without PATH, even which wouldn't be found, right? – Angew is no longer proud of SO Feb 5 '20 at 15:32
  • @AngewisnolongerproudofSO and without PATH, also man builtins wouldn't work :-) – andreee Feb 5 '20 at 15:53
  • 4
    There's no reason to ever use which. If you want to know about executables, use type with -a, -P, or -p. – wjandrea Feb 5 '20 at 21:47
  • 1
    @wjandrea what's wrong with which? – vikarjramun Feb 6 '20 at 17:40
  • 1
    By default type simply returns the first hit. If you want to see all of them, use type -a echo which will include the one found at /usr/bin. The difference between type and which is that which only looks at directories in your $PATH, while type will look everywhere, including shell builtins, functions etc. As a general rule, type is always preferred over which, for this reason among others. – terdon Feb 7 '20 at 12:12
3

The model employed by the Single Unix Specification (a.k.a. IEEE 1003.1) is that whether a command is built into a shell is a mere optimization, and the behaviour (if invoked in a conformant manner) should be the same for a built-in version of a command as for an external version. (This is regular built-ins, that is. Special built-ins are another matter.) In particular, if the command is not found as an external in a PATH search, the built-in version is not to be executed.

This is indeed what happens with one shell. You'll find that the Watanabe shell conforms to the SUS. In its posixly-correct mode, if echo is not on the path, the built-in echo command in the Watanabe shell will not be executed.

But the 93 Korn, Debian Almquist, Z, and Bourne Again shells in their most conformant modes still all execute built-ins even if there is no corresponding executable on PATH. That is what is happening here for you. The Bourne Again shell has a built-in echo command, and several others besides. It is executing that, even though it has not found an external echo command in a PATH search.

(Note that there are quite a few ways to invoke echo in a non-conformant manner, or at least in a manner where the result is unspecified: Using -n; using a backslash in any argument; using -e; using other things expecting them to be command options or end of options markers. These not only reveal whether it is a built-in echo, but even to an extent reveal what shell is in use. Fortunately, you did not hit any of them. ☺)

Further reading

1
  • 1
    I suspect the reason a lot of shells stil invoke a builtin even if the exacutable is present is the same they have it as a builtin to begin with, speed. Searching for the exacutable wastes time, and they have those builtins specifically to save time. – Mr Redstoner Feb 8 '20 at 9:01

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.