| Advanced Bash-Scripting Guide: A complete guide to shell scripting, using Bash | ||
|---|---|---|
| Prev | Chapter 3. Tutorial / Reference | Next |
3.12. Command Substitution
- Command substitution
Command substitution reassigns the output of a command or even multiple commands; it literally plugs the command output into another context.
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` 2 # "filename" contains a list of files to delete. 3 # 4 # S. C. points out that "arg list too long" error might result. 5 # Better is xargs rm -- < filename 6 # ( -- covers those cases where "filename" begins with a "-" ) 7 8 textfile_listing=`ls *.txt` 9 # Variable contains names of all *.txt files in current working directory. 10 echo $textfile_listing 11 12 textfile_listing2=$(ls *.txt) # The alternative form of command substitution. 13 echo $textfile_listing 14 # Same result. 15 16 # A possible problem with putting a list of files into a single string 17 # is that a newline may creep in. 18 # 19 # A safer way to assign a list of files to a parameter is with an array. 20 # shopt -s nullglob # If no match, filename expands to nothing. 21 # textfile_listing=( *.txt ) 22 # 23 # Thanks, S.C.

Command substitution may result in word splitting.
1 COMMAND `echo a b` # 2 args: a and b 2 3 COMMAND "`echo a b`" # 1 arg: "a b" 4 5 COMMAND `echo` # no arg 6 7 COMMAND "`echo`" # one empty arg 8 9 10 # Thanks, S.C.

Word splitting resulting from command substitution may remove trailing newlines characters from the output of the reassigned command(s). This can cause unpleasant surprises.
1 dir_listing=`ls -l` 2 echo $dirlisting 3 4 # Expecting a nicely ordered directory listing, such as: 5 # -rw-rw-r-- 1 bozo 30 May 13 17:15 1.txt 6 # -rw-rw-r-- 1 bozo 51 May 15 20:57 t2.sh 7 # -rwxr-xr-x 1 bozo 217 Mar 5 21:13 wi.sh 8 9 # However, what you get is: 10 # total 3 -rw-rw-r-- 1 bozo bozo 30 May 13 17:15 1.txt -rw-rw-r-- 1 bozo 11 # bozo 51 May 15 20:57 t2.sh -rwxr-xr-x 1 bozo bozo 217 Mar 5 21:13 wi.sh 12 13 # The newlines disappeared.
Even when there is no word splitting, command substitution can remove trailing newlines.
1 # cd "`pwd`" # This should always work. 2 # However... 3 4 mkdir 'dir with trailing newline 5 ' 6 7 cd 'dir with trailing newline 8 ' 9 10 cd "`pwd`" # Error message: 11 # bash: cd: /tmp/file with trailing newline: No such file or directory 12 13 cd "$PWD" # Works fine. 14 15 16 17 18 19 old_tty_setting=$(stty -g) # Save old terminal setting. 20 echo "Hit a key " 21 stty -icanon -echo # Disable "canonical" mode for terminal. 22 # Also, disable *local* echo. 23 key=$(dd bs=1 count=1 2> /dev/null) # Using 'dd' to get a keypress. 24 stty "$old_tty_setting" # Restore old setting. 25 echo "You hit ${#key} key." # ${#variable} = number of characters in $variable 26 # 27 # Hit any key except RETURN, and the output is "You hit 1 key." 28 # Hit RETURN, and it's "You hit 0 key." 29 # The newline gets eaten in the command substitution. 30 31 Thanks, S.C.
The $(COMMAND) form has superseded backticks for command substitution.
1 output=$(sed -n /"$1"/p $file) 2 # From "grp.sh" example.
Examples of command substitution in shell scripts:
