echo
, meet which
Remember how echo
had the simple job to print back anything you told
it? It’s time to
meet another friend, which
. It’s more specific in what it wants to
hear from you. If you tell it the name of another program it tells you
how it knows that program. What does that mean? Let’s look. I’ve only
told you about echo
so far, so let’s ask which
about echo
like
this:
$ which echo
/bin/echo
That means that it knows echo
is in the /bin
directory, or at least
that’s where it is here on ellen
, my computer. It might be different
on yours.
Here, bash
reports the same as the old Bourne shell, that it’s in
/bin
. On zsh
, it looks like this:
ellen% which echo
echo: shell built-in command
So some programs, or “commands”, are so familiar to the shell that they’re built in.
which
, where are you?Let’s ask which
about which
.
$ which which
/usr/bin/which
So on the classic Bourne shell, which
is in the /usr/bin
directory.
The same is true on the bash
shell, while zsh
also has a built in
which
. See:
ellen% which which
which: shell built-in command
To round this out, I’ll show you what which
reports in my zsh
here
on my computer when I ask it about the three shells I’ve mentioned so
far.
ellen% which sh
/bin/sh
ellen% which bash
/bin/bash
ellen% which zsh
/usr/bin/zsh
Again, I’m typing what follows the %
-signs, and zsh
is typing the
rest back to me, both the prompt ellen%
and the answers to the
questions it got from which
.
So which
expects the name of programs and won’t understand any other
words.
ellen% which way to the top
way not found
to not found
the not found
/usr/bin/top
It’s not smart. It believes that way
, to
, the
and top
are the
names of programs, not parts of a sentence. Turns out it’s actually
right about top
, though. It’s a classic program that shows you how
much work the computer is doing right now. If you happen to start it and
don’t know what to do, you can press q to leave it. And what do I know,
maybe you have programs named “way”, “to” or “the” installed? I didn’t.
That’s not to say that echo
is smart about what you tell it either. It
can parrot it back, but it can’t “understand” it.
So far, I’ve been pretty careful to only use words with plain letters in my examples of “talking” to the shell. Even though I’ve asked questions like “Can I just type anything” and “which way to the top”, I haven’t even used a question mark.
The reason for this is that the shell itself (rather than programs, like
echo
or which
) has a special relationship to some of the special
characters like ?
, *
, #
and a few others, especially apostrophes
and quotation marks.
For example, the #
symbol means something that the shell just throws
away and does not pass along to the program. Like this:
$ echo now you see me # now you do not see me
now you see me
This #
symbol is meant for comments to other programmers (or to
yourself) rather than commands to the computer. Here’s another example,
one that’s more in that vein.
$ echo A mess of pottage # Here, I wanted the computer to write "A mess of pottage"
A mess of pottage
In a shell comment, you can use the weird characters without problem. The shell knows you’re just making a comment and doesn’t try to understand.
Be careful though: symbols mean different things in different contexts.
The #
is also often used as a prompt for the administrator. It
replaces the friendly $
or %
-sign to alert you that it has the power
to, for example, erase anything on the computer. That’s why it’s
important to learn to recognize your prompt. Think of the shell as your
eyes and ears in the computer world, and the prompt as the computer
asking for your input.
ellen% echo eight days a week # Say “eight days a week”
eight days a week
ellen% # even when I'm not commanding anything, I can make a comment
…later, if I switch to the administrator account:
ellen#
← the prompt has changed from %
to #~\\
~ellen# exit
←better just exit for now
These two uses of the old #
are completely unrelated (and it’s only a
coincidence that the two different things both show as a #
). It’s
strange… the comment is so safe, it means “don’t worry, this is only a
side remark for other humans, the computer won’t mess anything up since
it’ll just throw this part of the text away” while the administrator
user prompt #
means “Please be careful, remember that you have great
power”.
We talked earlier about how which
sometimes showed us programs that
were placed in directories, and sometimes showed us commands that were
built-in to the shell. There is a third type of command that the shell
can use, and that’s “functions”.
I’ll show you a simple one, to start with. This is on zsh
:
ellen% vegetable () {
echo I like to eat aubergines
}
Weird, right? I’ll go through it row by row. Let’s say I wanted to often have the computer write to me how much it likes to eat aubergines. I could easily ask it to say that, like this:
ellen% echo I like to eat aubergines
I like to eat aubergines
But what if I wanted to do it with just a simple command? Like this:
ellen% vegetable
I like to eat aubergines
So the first line was vegetable () {
. Now, vegetable
is just the
name of the new command. I could’ve used any word (hopefully not a word
that the computer already expects to have meaning, but I can check that
with which
if I am unsure). The parentheses is how we let the shell
know that we’re teaching it a new function. And the curly braces, these:
{}
, well, they surround the list of commands that the shell should do
everytime the new function is called. In this case, all I’ve asked it to
do is to echo
something back at me.
When using <code>zsh</code>’s built-in version of which
, it even
knows about it:
ellen% which vegetable
vegetable () {
echo I like to eat aubergines
}
And I can call it how many times I want:
ellen% vegetable
I like to eat aubergines
ellen% vegetable
I like to eat aubergines
ellen% vegetable
I like to eat aubergines
This makes me happy. The computer now likes to eat aubergines. Teaching the shell new functions like this is great, because it can do many things at once.
Let’s say I wanted it to both praise eating potatoes and to tell me how
it knows about echo
:
ellen% potatowhich () {
echo I like some potatoes
which echo
}
ellen% potatowhich
I like some potatoes
echo: shell built-in command
The shell treats our homemade functions no different than the programs
it finds in files in places like /usr/bin
, and no different than the
built-in shell commands either.
Before you get carried away and write hundreds of nifty functions, remember that just defining the functions at the prompt like this does not save them. Be sure to save them in a text file.