Backticks vs braces in Bash

When I went to answer this question, I was going to use the ${} notation, as I've seen so many times on here that it's preferable to backticks.

However, when I tried

joulesFinal=${echo $joules2 \* $cpu | bc}

I got the message

-bash: ${echo $joules * $cpu | bc}: bad substitution

but

joulesFinal=`echo $joules2 \* $cpu | bc`

works fine. So what other changes do I need to make?


Solution 1:

The `` is called Command Substitution and is equivalent to $() (parenthesis), while you are using ${} (curly braces).

So all of these expressions are equal and mean "interpret the command placed inside":

joulesFinal=`echo $joules2 \* $cpu | bc`
joulesFinal=$(echo $joules2 \* $cpu | bc)
#            v                          v
#      ( instead of {                   v
#                                 ) instead of }

While ${} expressions are used for variable substitution.

Note, though, that backticks are deprecated, while $() is POSIX compatible, so you should prefer the latter.


From man bash:

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

          $(command)
   or
          `command`

Also, `` are more difficult to handle, you cannot nest them for example. See comments below and also Why is $(...) preferred over ... (backticks)?.

Solution 2:

They behave slightly differently in a specific case:

$ echo "`echo \"test\" `"
test

$ echo "$(echo \"test\" )"
"test"

So backticks silently remove the double quotes.

Solution 3:

${} refer to Shell parameter expansion. Manual link:https://www.gnu.org/software/bash/manual/html_node/Shell-Parameter-Expansion.html

The ‘$’ character introduces parameter expansion, command substitution, or arithmetic expansion. The parameter name or symbol to be expanded may be enclosed in braces, which are optional but serve to protect the variable to be expanded from characters immediately following it which could be interpreted as part of the name.

When braces are used, the matching ending brace is the first ‘}’ not escaped by a backslash or within a quoted string, and not within an embedded arithmetic expansion, command substitution, or parameter expansion.

FULLPATH=/usr/share/X11/test.conf_d/sk-synaptics.conf
 echo ${FULLPATH##*/}
echo ${FILENAME##*.}

First echo will get filename. second will get file extension as per manual ${parameter##word} section.


$(command)

`command`

refer to command substitution.

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.

https://www.gnu.org/software/bash/manual/html_node/Command-Substitution.html