Section 28.14 introduced command
substitution with a pair of backquotes (''
).
Let's review. The shell runs a backquoted string as a command, then replaces the
string with its output. Sometimes — though not as often — you'll want to use the
results from one backquoted string as arguments to another command, itself also
inside backquotes. To do that, you need to nest the backquotes to tell the shell
which command (which set of backquotes) should be done first, with its output
given to the second command. This is tricky with backquotes; the Korn shell
introduced an easier way that you'll see below. Here's a simple example — the
first command line uses nested backquotes, and the next two commands show its
parts:[4]
$echo "Next year will be 200`expr \`date +%y\` + 1`."
Next year will be 2002. $date +%y
01 $expr 01 + 1
2
The command to run first has escaped
backquotes (\'\'
) around it. In the example
above, that's the date +%y
command. date +%y
outputs the year — in this case, 01
— and that value is passed to the expr command. expr adds 01 and 1 to get 2. Then that result (from the outer
backquotes) is passed to echo, on its command
line, and echo prints the
message.
Why does the inner command, inside the escaped backquotes
(\'\'
), run first? It's because the
backslash before the backquote turns off the special
meaning (Section
27.12) of the backquote. When the shell first evaluates the command line,
which backquotes does it see? It sees the unescaped backquotes, the ones around
the expr
command, and the shell runs the
command:
expr `date +%y` + 1
But
when the shell evaluates that command line, it sees the backquotes in it (now
unescaped) and runs that command — date +%y
. The date +%y
command
outputs 01
. Next, the shell can finish the
command expr 01 + 1
. It outputs 2. Then the
echo command can print its
message.
Whew. Most newer Bourne-type shells have
an easier way: the $(
command
)
operators. Use $(
before the command, where you would use an opening backquote.
Put the )
after the command, in place of a
closing backquote. You don't have to escape these operators when you nest
them.
Here's the previous example with $(
)
, then a more real-life example:
2>&1
Section 36.16
$echo "Next year will be 200$(expr $(date +%y) + 1)."
Next year will be 2002. $tarout=$(tar cf /dev/rst1 $(find . -type f -mtime -1 -print) 2>&1)
time passes... $echo "$tarout"
tar: ./files/145923: Permission denied
The inner command — in this case, the find (Section 9.1) — is run first. Its output, a list of filenames, is put on the command line of the tar (Section 38.2) command. Finally, the output of tar (in this case, an error message) is stored in the tarout shell variable.
Beginners (and some long-time programmers too) might argue that you should never nest command substitution because it's too confusing. I think there are times nesting is clearer. It's more compact and doesn't need temporary storage. And it's not that hard to understand once you see what's happening. There's another nice example in Section 24.16.
— JP
[4] True, this won't work after 2008. Also true, most shells have built-in arithmetic, and some can zero-pad results. But this is a simple example!