160

I just want to understand following line of code in shell. It is used to get the current working directory. I am aware that $(variable) name return the value inside the variable name, but what is $(command) supposed to return? Does it return the value after executing the command? In that case, we can use ` to execute the command.

CWD="$(cd "$(dirname $0)"; pwd)"

Same output can be taken from the following line of code also in different version of shell

DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"

I am unable to understand the meaning of $(cd.. and $(dirname.

Could anybody help me to figure out how this command get executed?

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
KItis
  • 5,476
  • 19
  • 64
  • 112
  • 3
    And here is a question about the advantages/disadvantages of `$()` vs. `\`\``: http://stackoverflow.com/questions/9449778/what-is-the-benefit-of-using-instead-of-backticks-in-shell-scripts – None Dec 15 '16 at 22:20

2 Answers2

153

Usage of the $ like ${HOME} gives the value of HOME. Usage of the $ like $(echo foo) means run whatever is inside the parentheses in a subshell and return that as the value. In my example, you would get foo since echo will write foo to standard out

Eric Urban
  • 3,671
  • 1
  • 18
  • 23
  • 40
    Yes; `$(...)` is a better way of writing a command than trying to use back quotes. Consider writing: `gcclib=$(dirname $(dirname $(which gcc)))/lib` using back quotes. Even before you get into the difficulties of doing it in Markdown, it is harder because you have to escape the backquotes of the nested commands, whereas you don't with the `$(...)` notation. – Jonathan Leffler Aug 01 '13 at 04:03
  • 8
    Technically, `$(echo foo)` creates a command substitution, not a subshell. The other current answer gets this right. I think command substitution is run in a subshell, sort of, but they are still different concepts. – trysis Jul 13 '15 at 13:55
  • 9
    @trysis - command substitution [**definitely** runs in a subshell](https://www.gnu.org/software/bash/manual/html_node/Command-Substitution.html), and so it's worth noting it. – Eliran Malka Jan 09 '17 at 10:29
  • 2
    I understand that the backticks produce the same result as $(), but is the difference purely cosmetic? is there a reason to use one versus the other, apart from that the $() is more legible? – Mitchell Tracy Apr 30 '17 at 21:37
  • 4
    *"Usage of the $ like $(echo foo) means run whatever is inside the parentheses in a subshell and return that as the value."*...This is confusing, as this command `$(echo foo)` will try to **run what is returned** from the parentheses, it will first run `echo foo` then will try to run `foo` which gives an error – Accountant م Apr 18 '19 at 17:25
26
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"

Could anybody help me to figure out how this command get executed?

Let's look at different parts of the command. BASH_SOURCE is a bash array variable containing source filenames. So "${BASH_SOURCE[0]}" would return you the name of the script file.

dirname is a utility provided by GNU coreutils that remove the last component from the filename. Thus if you execute your script by saying bash foo, "$( dirname "${BASH_SOURCE[0]}" )" would return .. If you said bash ../foo, it'd return ..; for bash /some/path/foo it'd return /some/path.

Finally, the entire command "$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" gets the absolute directory containing the script being invoked.

$(...) allows command substitution, i.e. allows the output of a command to replace the command itself and can be nested.

AkaZecik
  • 980
  • 2
  • 11
  • 16
devnull
  • 118,548
  • 33
  • 236
  • 227
  • 1
    Sorry for being 3 years late to the party, but could you please explain *why* the statement works? You said `dirname` returns the path of the file executed (relative or absolute to the present working directory), `cd` changes the pwd to that directory, and `pwd` prints out the absolute path of the current working directory. But why are they joined by `&&`? And what will `DIR` hold if the `cd` fails? – Christian Sep 09 '16 at 08:42
  • 3
    @Christian, `&&` prevents the `pwd` from running if the `cd` fails, such that `DIR` will be empty rather than having an incorrect directory. – Charles Duffy Dec 23 '18 at 20:07