Updated: 2017-12-20 11:15 EST

1 Shell Command Substitution – interpolate stdout into a command lineIndexup to index

You are already familiar with the shell interpolating text into a command line from a variable, e.g.

$ var="Hello Mother"
$ echo "I said: $var"
I said: Hello Mother

The shell can also interpolate text that is the standard output (stdout) of a command or list of commands using a similar syntax to variable substitution. This is called Command Substitution.

The syntax for Command Substitution to interpolate the output of a command line into another command line uses a dollar sign and matched parentheses with the command line (any command line!) inside the parentheses:

$ whoami
idallen
$ echo "Your userid is $(whoami) on this system."
Your userid is idallen on this system.

$ date
Thu Nov 19 11:58:55 EST 2015
$ echo "The date is $(date) today."
The date is Thu Nov 19 11:58:59 EST 2015 today.

$ wc -l </etc/passwd
247
$ echo "The password file has $(wc -l </etc/passwd) lines"
The password file has 247 lines

The shell first executes the command inside the parentheses and interpolates the standard output of the command into the command line, then runs the resulting command line. The spaces around the command line inside the parentheses are optional, just as they would be optional if you typed the command directly into the shell:

$ echo "You can write '$( whoami )' or you can write '$(whoami)'."
You can write 'abcd0001' or you can write 'abcd0001'.

This shell interpolation of command standard output into the command line is called Command Substitution and you can read all about it in the man page for your shell.

You can use command substitution to interpolate text anywhere that you might use a shell variable. Command substitution is especially useful in shell scripting.

In scripting, we often use command substitution to set the value of a shell variable, and then use the value of the variable in the command we want to run:

lines=$( wc -l </etc/passwd )
echo "The password file has $lines lines"

Setting a variable in the script has many advantages:

Example: Put these script lines below into a file named commandsub.sh and make it executable and then run it.

The first three lines of the script are a copy of the standard script header:

#!/bin/sh -u
PATH=/bin:/usr/bin ; export PATH
umask 022

# The lines below are the body of this shell script:
#
user=$( whoami )                # save in a variable for multiple later use
echo "$0: You are logged in as $user.  In the passwd file you are:"
fgrep "$user" /etc/passwd

echo "$0: There are $(who | wc -l) users logged in."

numuser=$( who | fgrep -c "$user" )  
echo "$0: User '$user' is logged in $numuser times."

Run the script:

$ ./commandsub.sh
./commandsub.sh: You are logged in as abcd0001.  In the passwd file you are:
abcd0001:x:1000:1000:Some Student:/home/abcd0001:/bin/bash
./commandsub.sh: There are 5 users logged in.
./commandsub.sh: User 'abcd0001' is logged in 1 times.

If a different user ran the script, the output of whoami would be different and the script would output the information for that user.

2 Old syntax command substitution uses back-quotes (accent grave `…`)Indexup to index

Older shell scripts use a different syntax for their command substitution. Instead of using the modern dollar syntax and matching parentheses, older scripts surround the command with back-quote (accent grave) characters (`…`):

$ echo "Your userid is $(whoami)."
Your userid is idallen.
$ echo "Another way to say this is with back-quotes `whoami`."
Another way to say this is with back-quotes idallen.

The modern syntax with dollar sign and matching parentheses is preferred over the old way with back-quotes, but many old scripts still use back-quotes. Of the 202 scripts in the standard bin directories on the CLS right now, 115 of them contain back-quote characters:

$ file /bin/* /usr/bin/* | fgrep -c 'shell script'
202

$ file /bin/* /usr/bin/* | fgrep 'shell script' | awk -F: '{print $1}'
[... list of 202 file names that are shell scripts prints here...]

$ fgrep -l '`' $( file /bin/* /usr/bin/* | fgrep 'shell script' | awk -F: '{print $1}' ) | wc -l
115  

2.1 Quoting to prevent back-quote command substitutionIndexup to index

Like shell variables and the dollar-sign form of command substitution, back-quotes also expand inside double quotes; you need backslashes or single-quotes to hide them from the shell:

$ echo 'Hide back quotes like `whoami` inside single quotes.'
Hide back quotes like `whoami` inside single quotes.

$ echo "Use backslashes like \`whoami\` inside double quotes."
Use backslashes like `whoami` inside double quotes.
Author: 
| Ian! D. Allen, BA, MMath  -  idallen@idallen.ca  -  Ottawa, Ontario, Canada
| Home Page: http://idallen.com/   Contact Improv: http://contactimprov.ca/
| College professor (Free/Libre GNU+Linux) at: http://teaching.idallen.com/
| Defend digital freedom:  http://eff.org/  and have fun:  http://fools.ca/

Plain Text - plain text version of this page in Pandoc Markdown format

Campaign for non-browser-specific HTML   Valid XHTML 1.0 Transitional   Valid CSS!   Creative Commons by nc sa 3.0   Hacker Ideals Emblem   Author Ian! D. Allen