What is this form variable=$(...)

From the Bash manual (man bash):

   Command Substitution
       Command substitution allows the output of a command to replace the
       command name.  There are two forms:

              $(command)
       or
              `command`

       Bash performs the expansion by executing command in a subshell
       environment and replacing the command substitution with the standard
       output of the command, with any trailing newlines deleted.  Embedded
       newlines are not deleted, but they may be removed during word
       splitting.  The command substitution $(cat file) can be replaced by the
       equivalent but faster $(< file).

(This holds true for all Bourne-like shells, i.e. sh, ksh, zsh, bash etc., and zsh is also able to capture data with embedded NUL characters in this way)

The command

basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")

will assign the name of the directory where the script is located (while also changing all backslashes into forward slashes) to the variable basedir. Any errors, warnings or other diagnostic messages that are outputted to the standard error stream will still be displayed on the terminal ($(...) only captures the standard output of the command).

The shell will start by executing the innermost command substitution:

echo "$0" | sed -e 's,\\,/,g'

The output of that will be given as a string to dirname, and the output of that will be assigned to the variable basedir.

The double quotes are there to make sure that no word-splitting or filename globbing will be done, otherwise you may find that the script fails or produce strange output when $0 (the name of the script including the path used to execute it) contains a space character or a filename globbing character (such as ? or *).

It is in general a good idea to always quote expansions (variable expansions, command substitutions, and arithmetic expansions). See this question and its answers for an excellent explanation as to why this is a good idea.

If the script was executed as

$ /usr/local/bin/script.sh

then basedir will get the value of /usr/local/bin.

Or, on Cygwin:

$ bash c:\\Users\\Me\\script.sh

then basedir will get the value of c:/Users/Me. The double backslashes on the command line in this case is just to escape the single backslashes from the shell. The actual value of $0 is c:\Users\Me\script.sh.

Another way of doing the same thing without using dirname, echo and sed would be

basedir="${0//\\//}"
basedir="${basedir%/*}"

It means to run what is inside the parentheses in a subshell and return that as a value, in your case assigning that to varible.


The varible=$(..) called Command substitution and it's means nothing more but 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)"

and for store it to a variable:

SERVERNAME=$(hostname)

For more info: https://www.cyberciti.biz/faq/unix-linux-bsd-appleosx-bash-assign-variable-command-output/

Tags:

Shell