What is command substitution in a shell?

47,033

"Command substitution" is the name of the feature of the shell language that allows you to execute a command and have the output of that command replace (substitute) the text of the command.

There is no other feature of the shell language that allows you to do that.

A command substitution, i.e. the whole $(...) expression, is replaced by its output, which is the primary use of command substitutions.

The command that the command substitution executes, is executed in a subshell, which means it has its own environment that will not affect the parent shell's environment.

Not all subshell executions are command substitutions though (see further examples at end).

Example showing that a command substitution is executed in a subshell:

$ s=123
$ echo "hello $( s=world; echo "$s" )"
hello world
$ echo "$s"
123

Here, the variable s is set to the string 123. On the next line, echo is invoked on a string containing the result of a command substitution. The command substitution sets s to the string world and echoes this string. The string world is the output of the command in the command substitution and thus, if this was run under set -x, we would see that the second line above would have been expanded to echo 'hello world', which produces hello world on the terminal:

$ set -x
$ echo "hello $( s=world; echo "$s" )"
++ s=world
++ echo world
+ echo 'hello world'
hello world

(bash adds an extra level of + prompts to every level of a command substitution subshell in the trace output, other shells may not do this)

Lastly, we show that the command inside the command substitution was run in its own subshell, because it did not affect the value of s in the calling shell (the value of s is still 123, not world).

There are other situations where commands are executed in subshells, such as in

echo 'hello' | read message

In bash, unless you set the lastpipe option (only in non-interactive instances), the read is executed in a subshell, which means that $message will not be changed in the parent shell, i.e. doing echo "$message" after the above command will echo an empty string (or whatever value $message was before).

A process substitution in bash also executes in a subshell:

cat < <( echo 'hello world' )

This too is distinct from a command substitution.

Share:
47,033

Related videos on Youtube

user9303970
Author by

user9303970

Updated on September 18, 2022

Comments

  • user9303970
    user9303970 almost 2 years

    I'm using Ubuntu 16.04 with Bash and I tried to read in Wikipedia, in here and in here, but I failed to understand the meaning of "command substitution" in shell-scripting in general, and in Bash in particular, as in:

    $(command)
    

    or

    `command`
    

    What is the meaning of this term?

    Edit: When I first published this question I already knew the pure concept of substitution and also the Linux concept of variable substitution (replacing a variable with its value by execution), yet I still missed the purpose of this shell feature from the documentation for whatever reason or group of reasons.


    My answer after question locked

    Command substitution is an operation with dedicated syntax to both execute a command and to have this command's output hold (stored) by a variable for later use.

    An example with date:

    thedate="$(date)"
    

    We can then print the result using the command printf:

    printf 'The date is %s\n' "$thedate"
    
    1. The command substitution syntax is $().
    2. The command itself is date.
    3. Combining both we get $(date), its value is the result of the substitution (that we could get after execution).
    4. We save that value in a variable, $thedate, for later use.
    5. We display the output value held by the variable with printf, per the command above.

    Note: \n in printf is a line-break.

  • Stéphane Chazelas
    Stéphane Chazelas about 6 years
    result here is the standard output of the command stripped of all its trailing newline characters (and some variations in between shells if the output is non-text). Note that `...` is the Bourne of csh syntax while $(...) is the Korn/POSIX syntax (with `...` still supported for backward compatibility)
  • Vlastimil Burián
    Vlastimil Burián about 6 years
    @StéphaneChazelas Thank you for valuable information, and feel free to edit the answer for it to include it.