7

I wanted to find the read command, so I did:

$ which read

It returns exit status 1. Why does this happen?

Eliah Kagan
  • 117,780

2 Answers2

18

read is a shell builtin, not an external command. which only tells you about external commands. Assuming you're using Bash (or some other Bourne-style shell), you should typically use type or command -v instead of which.

ek@Cord:~$ type read
read is a shell builtin

type and command are themselves shell builtins and they know not just about external commands but also about keywords, builtins, aliases, and functions. which is an external command that doesn't know about those things; it only knows about external commands. Sometimes which doesn't turn up anything when you ask it about a command that you can use in your shell. Sometimes it does turn up something for a command, but it isn't the same thing that actually runs when you use the command in your shell.

ek@Cord:~$ type type command which
type is a shell builtin
command is a shell builtin
which is /usr/bin/which

In Bash, you can see all the current possible meanings for a command, in the order that they are tried, with type -a:

ek@Cord:~$ type -a read
read is a shell builtin
ek@Cord:~$ type -a echo
echo is a shell builtin
echo is /bin/echo

For more information about why you usually shouldn't use which, and what to use instead in various shells including Bash, see Why not use “which”? What to use then?

Eliah Kagan
  • 117,780
  • 1
    Like cd, read is always a builtin because it modifies shell internal state, so it couldn't be implemented as a separate program. – Simon Richter Jul 02 '19 at 10:24
1

If you know a little how UNIX and the shell work, it should be obvious from the syntax (read var1 var2 ...) that no external program can set a local shell variable, so read must be built into the shell.

In bash you do not just get an exit code of 1, but also a message like which: no read in (/home/user/bin:/usr/local/bin:/usr/bin:/bin:/usr/bin/X11:/usr/games). That should ring a bell that if read is still found, it must be built-in to the shell.

U. Windl
  • 243
  • 4
    easy there buddy. Your info is correct but the way you wrote it sounds a little arrogant. A lot of people don't have deep knowledge of how Linux works and to many such knowledge is not otherwise useful – 520 Jul 02 '19 at 15:03
  • @U.Windl When run from bash on Ubuntu, which read prints no message. It appears you're on a system whose which executable is provided by GNU which. But /bin/which in Ubuntu is from debianutils. Some shells have a which builtin but bash doesn't. The behavior of the external command which varies greatly by OS, including across GNU/Linux distros. This is one of several reasons to prefer type or command -v. (On some OSes, which is even a csh script.) – Eliah Kagan Jul 02 '19 at 18:57
  • What do you mean from "it should be obvious from the syntax (read var1 var2 ...) that no external program can set a local shell variable"? I haven't heard it before. – Mohammad Kholghi Jul 04 '19 at 08:38
  • @Mohammad Kholghi: Try writing a command in any language you like (including a shell script) that sets a shell variable that still exists after the command ended. That's what I meant: All variable setting in a process are gone when the process exits. Maybe really think about it, then think how an external read program should work. – U. Windl Jul 04 '19 at 09:19
  • Ahaaa. I didn't know it. Thanks! @U.Windl – Mohammad Kholghi Jul 05 '19 at 11:42
  • 1
    @520 I agree with these remarks—it’s best to communicate the why and the how and not so much make assumptions about prior knowledge, after all this is a Q&A site for people who are often trying to learn new things. What you have touched on in this answer is interesting and it would be much more helpful with some extra detail and with less passive aggression – gdgr Jul 07 '19 at 02:02