2

I raised a few server environments with Ubuntu and Bash, on "self managed shell" hosting providers like DigitialOcean, on which I ran Drupal/WordPress applications.

All that time I didn't have a necessity to use what's called "command substition".

I ask, what will be a problem, a "pattern" in which a Bash programmer would have to use this concept? Please give an example?

5 Answers5

6

Command substitution means to run a shell command and store its output to a variable or display back using echo command. For example, display date and time:

echo "Today is $(date)"

It is useful in situations where my command receives as parameter the output of another command or example.

vfbsilva
  • 3,697
  • 2
    That's an unfortunate example in that date could do the same thing with date +'Today is %a %b %e %H:%M:%S %Z %Y' and also because printf is preferable over echo when outputting variable data. – Kusalananda Jun 10 '18 at 19:58
  • Also, date | sed 's/^/Today is /'... Using a command substitution to display data using echo is simply not a good or even idiomatic example of the use of command substitutions. – Kusalananda Jun 11 '18 at 06:58
  • vfbsilva you might want to change the example to use printf and not use date? – Arcticooling Jun 11 '18 at 14:07
  • I might, problem is than I will be answering another questions. You can accept the next answer I couldn't care less the point is im not here to discuss best practices I was just showing a concept which imho was properly presented than this became code golfing and I'm not on the mood – vfbsilva Jun 11 '18 at 18:26
4

From the Command Substitution subsection in the POSIX standard:

Command substitution allows the output of a command to be substituted in place of the command name itself.

Command substitutions allow for a handy way of making use of a command's output without the need for first writing it to a temporary file and then reading it in from that file. This is best done if the command's output is a short string on a single line.

Some people use command substitutions to collect output from a command even though the amount of output may be a multi-line document. This is generally not a good way of using command substitution. Instead, the standard Unix idiom of passing data between processing stages using pipelines or temporary files should be used.


Examples of command substitutions that I use:

For example, to figure out whether the current user is executing the script as root:

if [ "$( id -u )" -ne 0 ]; then
   echo 'This script requires root privileges, re-run with sudo' >&2
   exit 1
fi

The $(id -u) command substitution will be substituted with the output of id -u, which will return the UID (an integer) of the current user.

Another example. I'm using GnuPG to sign git commits. For GnuPG to work properly, I need to set GPG_TTY to the name of the current terminal device in my interactive shell's initialization file. I do this with

export GPG_TTY="$( tty )"

This sets GPG_TTY to something like /dev/ttyp4 depending on what the current terminal device is in the shell session.

Another example. I have a script that has to treat running on a Solaris machine as a special case:

case "$( uname -s )" in
    SunOS)
        # code specific for Solaris
        ;;
    *)
        # code for all other Unix platforms
esac

Another example. The getconf PATH command returns the "default path" for the current system. I use it under some circumstances to reset the PATH variable to a "sane default" value:

PATH="$( getconf PATH )"
Kusalananda
  • 333,661
3

I use it with find a lot, such as:

tar cvf ../junk.tar `find .`

Also, as part of a poor-man's IDE:

vi `grep mysearcstring *.[ch]`

The above are command-line examples. I also use it in scripts a lot, and would be hard-pressed without it. The most common case is probably as mentioned above, to set shell variables from the output of a command:

NOW=`date`

I use back-quotes by old habit, but the $(command) syntax is far better since you can embed one inside another. With back-quotes, you have to know just where to put the escape \ characters and it's a nuisance.

2

Another example:

  • In Docker you can clean off stopped containers using:

    docker rm containerID containerID containerID ...`
    
  • You can also get the ids of the containers that have stopped running with:

    docker ps -q -f "status=exited" 
    
  • So you can clean off all the stopped containers with:

    docker rm $(docker ps -q -f "status=exited")
    

... where the ids produced by docker ps are substituted to the $(docker ps...) string to be used by the docker rm command.

xenoid
  • 8,888
2

The implementation pattern that makes this usage necessary is that Unix shells execute each non-builtin command in a child process. The child process cannot modify the context of its parent. Command substitution can cause the shell to use textual output of a non-builtin command as if it had been written in the shell script or typed on the command line.