7 How Shell See
7 How Shell See
In this chapter we are going to look at some of the “magic” that occurs on the command
line when we press the Enter key. While we will examine several interesting and complex
features of the shell, we will do it with just one new command.
● echo – Display a line of text
Expansion
Each time we type a command and press the Enter key, bash performs several substitu-
tions upon the text before it carries out our command. We have seen a couple of cases of
how a simple character sequence, for example *, can have a lot of meaning to the shell.
The process that makes this happen is called expansion. With expansion, we enter some-
thing and it is expanded into something else before the shell acts upon it. To demonstrate
what we mean by this, let's take a look at the echo command. echo is a shell builtin that
performs a very simple task. It prints its text arguments on standard output.
That's pretty straightforward. Any argument passed to echo gets displayed. Let's try an-
other example.
So what just happened? Why didn't echo print *? As we recall from our work with wild-
cards, the * character means match any characters in a filename, but what we didn't see in
our original discussion was how the shell does that. The simple answer is that the shell
expands the * into something else (in this instance, the names of the files in the current
working directory) before the echo command is executed. When the Enter key is
68
Expansion
pressed, the shell automatically expands any qualifying characters on the command line
before the command is carried out, so the echo command never saw the *, only its ex-
panded result. Knowing this, we can see that echo behaved as expected.
Pathname Expansion
The mechanism by which wildcards work is called pathname expansion. If we try some
of the techniques that we employed in earlier chapters, we will see that they are really ex-
pansions. Given a home directory that looks like this:
[me@linuxbox ~]$ ls
Desktop ls-output.txt Pictures Templates
Documents Music Public Videos
and this:
or even this:
69
7 – Seeing the World as the Shell Sees It
Tilde Expansion
As we may recall from our introduction to the cd command, the tilde character (~) has a
special meaning. When used at the beginning of a word, it expands into the name of the
home directory of the named user or, if no user is named, the home directory of the cur-
rent user.
70
Expansion
Arithmetic Expansion
The shell allows arithmetic to be performed by expansion. This allows us to use the shell
prompt as a calculator.
Spaces are not significant in arithmetic expressions and expressions may be nested. For
example, to multiply 5 squared by 3, we can use this:
71
7 – Seeing the World as the Shell Sees It
75
Single parentheses may be used to group multiple subexpressions. With this technique,
we can rewrite the previous example and get the same result using a single expansion in-
stead of two.
Here is an example using the division and remainder operators. Notice the effect of inte-
ger division.
Brace Expansion
Perhaps the strangest expansion is called brace expansion. With it, we can create multiple
text strings from a pattern containing braces. Here's an example:
Patterns to be brace expanded may contain a leading portion called a preamble and a
trailing portion called a postscript. The brace expression itself may contain either a
comma-separated list of strings or a range of integers or single characters. The pattern
may not contain unquoted whitespace. Here is an example using a range of integers:
In bash version 4.0 and newer, integers may also be zero-padded like so:
72
Expansion
So, what is this good for? The most common application is to make lists of files or direc -
tories to be created. For example, if we were photographers and had a large collection of
images that we wanted to organize into years and months, the first thing we might do is
create a series of directories named in numeric “Year-Month” format. This way, the direc-
tory names would sort in chronological order. We could type out a complete list of direc-
tories, but that's a lot of work and it's error-prone. Instead, we could do this:
Pretty slick!
Parameter Expansion
We're going to touch only briefly on parameter expansion in this chapter, but we'll be
covering it extensively later. It's a feature that is more useful in shell scripts than directly
73
7 – Seeing the World as the Shell Sees It
on the command line. Many of its capabilities have to do with the system's ability to store
small chunks of data and to give each chunk a name. Many such chunks, more properly
called variables, are available for our examination. For example, the variable named
USER contains our username. To invoke parameter expansion and reveal the contents of
USER we would do this:
You may have noticed that with other types of expansion, if we mistype a pattern, the ex-
pansion will not take place, and the echo command will simply display the mistyped
pattern. With parameter expansion, if we misspell the name of a variable, the expansion
will still take place but will result in an empty string:
[me@linuxbox ~]$
Command Substitution
Command substitution allows us to use the output of a command as an expansion.
74
Expansion
getting the listing of the cp program without having to know its full pathname. We are
not limited to just simple commands. Entire pipelines can be used (only partial output is
shown here):
In this example, the results of the pipeline became the argument list of the file com-
mand.
There is an alternate syntax for command substitution in older shell programs that is also
supported in bash. It uses backquotes instead of the dollar sign and parentheses.
Quoting
Now that we've seen how many ways the shell can perform expansions, it's time to learn
how we can control it. Take for example the following:
or this one:
75
7 – Seeing the World as the Shell Sees It
In the first example, word-splitting by the shell removed extra whitespace from the echo
command's list of arguments. In the second example, parameter expansion substituted an
empty string for the value of $1 because it was an undefined variable. The shell provides
a mechanism called quoting to selectively suppress unwanted expansions.
Double Quotes
The first type of quoting we will look at is double quotes. If we place text inside double
quotes, all the special characters used by the shell lose their special meaning and are
treated as ordinary characters. The exceptions are $, \ (backslash), and ` (back-quote).
This means that word-splitting, pathname expansion, tilde expansion, and brace expan-
sion are suppressed, but parameter expansion, arithmetic expansion, and command sub-
stitution are still carried out. Using double quotes, we can cope with filenames containing
embedded spaces. Say we were the unfortunate victim of a file called two word-
s.txt. If we tried to use this on the command line, word-splitting would cause this to be
treated as two separate arguments rather than the desired single argument.
By using double quotes, we stop the word-splitting and get the desired result; further, we
can even repair the damage.
There! Now we don't have to keep typing those pesky double quotes.
Remember, parameter expansion, arithmetic expansion, and command substitution still
take place within double quotes.
76
Quoting
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29
We should take a moment to look at the effect of double quotes on command substitution.
First let's look a little deeper at how word splitting works. In our earlier example, we saw
how word-splitting appears to remove extra spaces in our text.
By default, word-splitting looks for the presence of spaces, tabs, and newlines (linefeed
characters) and treats them as delimiters between words. This means unquoted spaces,
tabs, and newlines are not considered to be part of the text. They serve only as separators.
Since they separate the words into different arguments, our example command line con-
tains a command followed by four distinct arguments. If we add double quotes:
word-splitting is suppressed and the embedded spaces are not treated as delimiters; rather
they become part of the argument. Once the double quotes are added, our command line
contains a command followed by a single argument.
The fact that newlines are considered delimiters by the word-splitting mechanism causes
an interesting, albeit subtle, effect on command substitution. Consider the following:
77
7 – Seeing the World as the Shell Sees It
24 25 26 27 28 29
In the first instance, the unquoted command substitution resulted in a command line con-
taining 38 arguments. In the second, it resulted in a command line with one argument that
includes the embedded spaces and newlines.
Single Quotes
If we need to suppress all expansions, we use single quotes. Here is a comparison of un-
quoted, double quotes, and single quotes:
[me@linuxbox ~]$ echo text ~/*.txt {a,b} $(echo foo) $((2+2)) $USER
text /home/me/ls-output.txt a b foo 4 me
[me@linuxbox ~]$ echo "text ~/*.txt {a,b} $(echo foo) $((2+2)) $USER"
text ~/*.txt {a,b} foo 4 me
[me@linuxbox ~]$ echo 'text ~/*.txt {a,b} $(echo foo) $((2+2)) $USER'
text ~/*.txt {a,b} $(echo foo) $((2+2)) $USER
As we can see, with each succeeding level of quoting, more and more of the expansions
are suppressed.
Escaping Characters
Sometimes we want to quote only a single character. To do this, we can precede a charac-
ter with a backslash, which in this context is called the escape character. Often this is
done inside double quotes to selectively prevent an expansion.
[me@linuxbox ~]$ echo "The balance for user $USER is: \$5.00"
The balance for user me is: $5.00
To allow a backslash character to appear, escape it by typing \\. Note that within single
78
Quoting
quotes, the backslash loses its special meaning and is treated as an ordinary character.
The table above lists some of the common backslash escape sequences. The idea
behind this representation using the backslash originated in the C programming
language and has been adopted by many others, including the shell.
Adding the -e option to echo will enable interpretation of escape sequences.
You may also place them inside $' '. Here, using the sleep command, a sim-
ple program that just waits for the specified number of seconds and then exits, we
can create a primitive countdown timer:
sleep 10; echo -e "Time's up\a"
Summing Up
As we move forward with using the shell, we will find that expansions and quoting will
be used with increasing frequency, so it makes sense to get a good understanding of the
way they work. In fact, it could be argued that they are the most important subjects to
79
7 – Seeing the World as the Shell Sees It
learn about the shell. Without a proper understanding of expansion, the shell will always
be a source of mystery and confusion, with much of its potential power wasted.
Further Reading
● The bash man page has major sections on both expansion and quoting which
cover these topics in a more formal manner.
● The Bash Reference Manual also contains chapters on expansion and quoting:
http://www.gnu.org/software/bash/manual/bashref.html
80