Command substitution reassigns the output of a command [1] or even multiple commands; it literally plugs the command output into another context. [2]
The classic form of command substitution uses backquotes (`...`). Commands within backquotes (backticks) generate command line text.
1 script_name=`basename $0` 2 echo "The name of this script is $script_name." |
The output of commands can be used as arguments to another command, to set a variable, and even for generating the argument list in a for loop.
1 rm `cat filename` # "filename" contains a list of files to delete. 2 # 3 # S. C. points out that "arg list too long" error might result. 4 # Better is xargs rm -- < filename 5 # ( -- covers those cases where "filename" begins with a "-" ) 6 7 textfile_listing=`ls *.txt` 8 # Variable contains names of all *.txt files in current working directory. 9 echo $textfile_listing 10 11 textfile_listing2=$(ls *.txt) # The alternative form of command substitution. 12 echo $textfile_listing2 13 # Same result. 14 15 # A possible problem with putting a list of files into a single string 16 # is that a newline may creep in. 17 # 18 # A safer way to assign a list of files to a parameter is with an array. 19 # shopt -s nullglob # If no match, filename expands to nothing. 20 # textfile_listing=( *.txt ) 21 # 22 # Thanks, S.C. |
Command substitution invokes a subshell. |
Using echo to output an unquoted variable set with command substitution removes trailing newlines characters from the output of the reassigned command(s). This can cause unpleasant surprises.
|
Command substitution even permits setting a variable to the contents of a file, using either redirection or the cat command.
1 variable1=`<file1` # Set "variable1" to contents of "file1". 2 variable2=`cat file2` # Set "variable2" to contents of "file2". 3 # This, however, forks a new process, 4 #+ so the line of code executes slower than the above version. 5 6 # Note: 7 # The variables may contain embedded whitespace, 8 #+ or even (horrors), control characters. |
1 # Excerpts from system file, /etc/rc.d/rc.sysinit 2 #+ (on a Red Hat Linux installation) 3 4 5 if [ -f /fsckoptions ]; then 6 fsckoptions=`cat /fsckoptions` 7 ... 8 fi 9 # 10 # 11 if [ -e "/proc/ide/${disk[$device]}/media" ] ; then 12 hdmedia=`cat /proc/ide/${disk[$device]}/media` 13 ... 14 fi 15 # 16 # 17 if [ ! -n "`uname -r | grep -- "-"`" ]; then 18 ktag="`cat /proc/version`" 19 ... 20 fi 21 # 22 # 23 if [ $usb = "1" ]; then 24 sleep 5 25 mouseoutput=`cat /proc/bus/usb/devices 2>/dev/null|grep -E "^I.*Cls=03.*Prot=02"` 26 kbdoutput=`cat /proc/bus/usb/devices 2>/dev/null|grep -E "^I.*Cls=03.*Prot=01"` 27 ... 28 fi |
Do not set a variable to the contents of a long text file unless you have a very good reason for doing so. Do not set a variable to the contents of a binary file, even as a joke. Example 11-1. Stupid script tricks
Notice that a buffer overrun does not occur. This is one instance where an interpreted language, such as Bash, provides more protection from programmer mistakes than a compiled language. |
Command substitution permits setting a variable to the output of a loop. The key to this is grabbing the output of an echo command within the loop.
Example 11-2. Generating a variable from a loop
1 #!/bin/bash 2 # csubloop.sh: Setting a variable to the output of a loop. 3 4 variable1=`for i in 1 2 3 4 5 5 do 6 echo -n "$i" # The 'echo' command is critical 7 done` #+ to command substitution here. 8 9 echo "variable1 = $variable1" # variable1 = 12345 10 11 12 i=0 13 variable2=`while [ "$i" -lt 10 ] 14 do 15 echo -n "$i" # Again, the necessary 'echo'. 16 let "i += 1" # Increment. 17 done` 18 19 echo "variable2 = $variable2" # variable2 = 0123456789 20 21 # Demonstrates that it's possible to embed a loop 22 #+ within a variable declaration. 23 24 exit 0 |
Command substitution makes it possible to extend the toolset available to Bash. It is simply a matter of writing a program or script that outputs to stdout (like a well-behaved UNIX tool should) and assigning that output to a variable.
|
The $(...) form has superseded backticks for command substitution.
The $(...) form of command substitution treats a double backslash in a different way than `...`.
The $(...) form of command substitution permits nesting. [3]
Or, for something a bit more elaborate . . . Example 11-3. Finding anagrams
|
Examples of command substitution in shell scripts:
[1] | For purposes of command substitution, a command may be an external system command, an internal scripting builtin, or even a script function. | |
[2] | In a more technically correct sense, command substitution extracts the stdout of a command, then assigns it to a variable using the = operator. | |
[3] | In fact, nesting with backticks is also possible, but only by escaping the inner backticks, as John Default points out.
|