Backticks vs braces in Bash
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
![rojomoke](https://i.stack.imgur.com/L7p6x.jpg?s=256&g=1)
rojomoke
Updated on December 19, 2021Comments
-
rojomoke over 2 years
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?
-
hek2mgl over 10 yearsI've investigated it, and I have to admit that backtics are indeed compatible with the POSIX standard. However, it is still true that bash deprecated them, and that
$()
is better to handle (+1) -
hek2mgl over 10 years... also found no "real" deprecation in the bash project, meaning a hint that backtics will be removed in upcoming versions. Seems using
$()
is just the preferred way. sorry for the confusion :) -
fedorqui over 10 yearsNo problem at all, @hek2mgl , I find it very interesting. I have sometimes read here in SO that it is deprecated, so it is common to think so (I even thought that). But for me, the most important reason to use
$()
instead of ` `` ` is the fact that with the first you can nest, while the second does not allow it. -
hek2mgl over 10 yearsnow we know :) .. Yeah, the possibility of nesting them with need to escape is a big advantage of
$()
! -
DevSolar over 10 yearsEven if you don't nest, backticks are easily overlooked in quite many console fonts.
$()
much less so. -
Daniel Lubarov over 8 yearsYou can nest with "``", it's just ugly. "echo `echo \`echo abc\``" works.
-
Chad Skeeters over 7 yearsInteresting example. I suspect that the contents of $() is run before the outer string has it's special characters handled as opposed to the case in which backquotes are used. If you want to use backquotes and have quotes persist,
echo "`echo \\"test\\"`"
will work as the bash slash escape character needs to be escaped for outer string parsing for it to persist for the inner command.