8.2 The Command Line

8.2.1 Running Programs

It's hard to get much accomplished without running a program; you might be able to prop something up with your computer or hold a door open, and some will make the most lovely humming noise when running, but that's really about it. And I think we can all agree that its use as a humming doorstop isn't what brought the personal computer the popularity it now enjoys.

So, remember how almost everything in Linux is a file? Well, that goes for programs, too. Every command you run (that isn't built into the shell) resides as a file somewhere. You run a program simply by specifying the full path to it.

For instance, remember that su command from the last section? Well, it's actually in the /bin directory: /bin/su would run it nicely.

So why, then, does just typing su work? After all, you didn't say it was in /bin. It could just as easily have been in /usr/local/share, right? How did it know? The answer to that lies in the PATH environment variable; most shells have either PATH or something very much like PATH. It basically contains a list of directories to look in for programs you try to run. So when you ran su, your shell ran through its list of directories, checking each one for an executable file called su that it could run; the first one it came to, it ran. This happens whenever you run a program without specifying a full path to it; if you get a ““Command not found”” error, that only means that the program you tried to run isn't in your PATH. (Of course, this would be true if the program doesn't exist at all...) We'll discuss environment variables in more depth in Section 8.3.1.

Remember also that “.” is shorthand for the current directory, so if you happened to be in /bin, ./su would have worked as an explicit full path.

8.2.2 Wildcard Matching

Nearly every shell recognizes some characters as being substitutes or abbreviations that mean anything goes here. Such characters are aptly named wildcards; the most common are * and ?. By convention, ? usually matches any single character. For instance, suppose you're in a directory with three files: ex1.txt, ex2.txt, and ex3.txt. You want to copy all of those files (using the cp command we cover in Section 10.5.1) to another directory, say /tmp. Well, typing cp ex1.txt ex2.txt ex3.txt /tmp is entirely too much work. It's much easier to type cp ex?.txt /tmp; the ? will match each of the characters “1”, “2”, and “3”, and each in turn will be substituted in.

What's that you say? That's still too much work? You're right. It's appalling; we have labor laws to protect us from that sort of thing. Fortunately, we also have *. As was already mentioned, * matches “any number of characters”, including 0. So if those three files were the only ones in the directory, we could have simply said cp * /tmp and gotten them all in one fell swoop. Suppose, though, that there is also a file called ex.txt and one called hejaz.txt. We want to copy ex.txt but not hejaz.txt; cp ex* /tmp will do that for us.

cp ex?.txt /tmp, would, of course, only get our original three files; there's no character in ex.txt to match that ?, so it would be left out.

Another common wildcard is the bracket pair [ ]. Any characters inside the brackets will be substituted in place of the [ ] to find matches. Sound confusing? It's not too bad. Suppose for instance, we have a directory containing the following 8 files: a1, a2, a3, a4, aA, aB, aC, and aD . We want to only find the files ending in numbers; [ ] will do this for us.

% ls a[1-4]
a1 a2 a3 a4

But what we really want is just a1, a2, and a4? In the previous example we used - to mean all values between 1 and 4. We can also separate individual entries with commas.

% ls a[1,2,4]
a1 a2 a4

I know what you're thinking now, “Well what about letters?” Linux is case-sensitive, meaning that a and A are different characters and are only related in your mind. Capitals always come before lowercase letters, so A and B come before a and b. Continuing with our earlier example, if we wanted files a1, and A1, we can find these quickly with [ ].

% ls [A,a]1
A1 a1

Note, that if we had included a hyphen instead of a comma, we would have gotten incorrect results.

% ls [A-a]1
A1 B1 C1 D1 a1

You can also combine hyphen and comma strings.

% ls [A,a-d]
A1 a1 b1 c1 d1

8.2.3 Input/Output Redirection and Piping

(Here comes something cool.)

% ps > blargh

Y'know what that is? That's me running ps to see which processes are running; ps is covered in Section 11.3. That's not the cool part. The cool part is > blargh, which means, roughly, take the output from ps and write it to a file called blargh. But wait, it gets cooler.

% ps | less

That one takes the output from ps and pipes it through less, so I can scroll through it at my leisure.

% ps >> blargh

This is the third most commonly used redirector; it does the same thing as “>”, except that “>>” will append output from ps to the file blargh, if said file exists. If not, just like “>”, it will be created. (“>” will obliterate the current contents of blargh.)

There is also a “<” operator, which means take your input from the following, but it's not used nearly so often.

% fromdos < dosfile.txt > unixfile.txt

Redirection gets really fun when you start piling it up:

% ps | tac >> blargh

That will run ps, reverse the lines of its output, and append those to the file blargh. You can stack as many of these up as you want; just be careful to remember that they get interpreted from left to right.

See the bash(1) man page for more detailed information on redirection.