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%/*}"
man bash
and search for Command substitution – FloHe Jan 21 '17 at 13:03