321

To store the output of a command as a variable in sh/ksh/bash, you can do either

var=$(command)

or

var=`command`

What's the difference if any between the two methods?

codeforester
  • 39,467
  • 16
  • 112
  • 140
hhafez
  • 38,949
  • 39
  • 113
  • 143

6 Answers6

329

The backticks/gravemarks have been deprecated in favor of $() for command substitution because $() can easily nest within itself as in $(echo foo$(echo bar)). There are other differences such as how backslashes are parsed in the backtick/gravemark version, etc.

See BashFAQ/082 for several reasons to always prefer the $(...) syntax.

Also see the POSIX spec for detailed information on the various differences.

SiegeX
  • 135,741
  • 24
  • 144
  • 154
  • 27
    Good link, but that text doesn't _deprecate_ backquotes in favour of `$(...)` – it just notes them as alternatives. – Norman Gray Jun 13 '14 at 15:04
  • 30
    @NormanGray POSIX may not say the word *deprecated* but it does say `"the backquoted variety of command substitution is not recommended"` which is just a long winded way of saying deprecated IMHO – SiegeX Dec 16 '15 at 05:13
  • 16
    POSIX did not deprecate backticks,but rather added `$(...)` as an alternative method. There is no known implementation bug with backticks, but there are many known implementation bugs with `$(...) `. So for portability issues it is recommended to use backticks for non-nested calls. `$(...)` needs a recursive parser but this was not used with ksh86 that introduced the feature. Check http://www.in-ulm.de/~mascheck/various/cmd-subst/ for a list of correct implementations. A conforming shell needs to support all cases except case D.2. – schily Feb 14 '16 at 12:31
  • 2
    There are other things in POSIX that need to be seen as `deprecated`, e.g. the use of `waitpid()` that prevents you from from seeing the full 32 bits from the `exit()` parameter, but all shells except the recent Bourne Shell still use `waitpid()` instead of the `waitid()` call that is now available since 26 years. – schily Feb 14 '16 at 12:36
  • 1
    The link in the answer hints that there are some differences between the backticks and `$()`, which is more explained [in this part of the documentation](http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_03). The differences is not only about nesting. – Some programmer dude Jul 10 '16 at 05:15
  • Is the eval bash specific? It will not start a subshell as opposed to starting a subshell by $(cmd) or \`cmd\` – Kemin Zhou May 07 '18 at 23:54
  • @KeminZhou... huh? Eval is not bash-specific, but I don't see what it has to do with any of this. If you want to run `cmd` in your current shell, the easiest way to do that is just `cmd`, not `eval cmd`. – Charles Duffy Jun 08 '22 at 20:19
43

They behave the same. The difference is syntactical: it's easier to nest $() than ``:

listing=$(ls -l $(cat filenames.txt))

vs.

listing=`ls -l \`cat filenames.txt\``
John Kugelman
  • 349,597
  • 67
  • 533
  • 578
  • 11
    `echo $(echo \$abc)` is not the same as ``echo `echo \$abc`‍`` - Differences also exist for ``$(echo \`)`` and ``$(echo \\)`` – Peter.O Aug 10 '15 at 22:34
  • 2
    Another difference is: `echo foo \`#comment\`` vs `echo foo $(#comment)`. The second one doesn't work. (Used for commenting in a multi-line command.) – wisbucky Jul 10 '19 at 22:02
30

July 2014: The commit f25f5e6 (by Elia Pinto (devzero2000), April 2014, Git 2.0) adds to the nesting issue:

The backquoted form is the traditional method for command substitution, and is supported by POSIX.
However, all but the simplest uses become complicated quickly.
In particular, embedded command substitutions and/or the use of double quotes require careful escaping with the backslash character
.

That is why the git/Documentation/CodingGuidelines mentions:

We prefer $( ... ) for command substitution; unlike ``, it properly nests.
It should have been the way Bourne spelled it from day one, but unfortunately isn't.

thiton commented:

That is why `echo `foo`` won't work in general because of the inherent ambiguity because each ``can be opening or closing.
It might work for special cases due to luck or special features.


Update January 2016: Git 2.8 (March 2016) gets rid of backticks entirely.

See commit ec1b763, commit 9c10377, commit c7b793a, commit 80a6b3f, commit 9375dcf, commit e74ef60, commit 27fe43e, commit 2525c51, commit becd67f, commit a5c98ac, commit 8c311f9, commit 57da049, commit 1d9e86f, commit 78ba28d, commit efa639f, commit 1be2fa0, commit 38e9476, commit 8823d2f, commit 32858a0, commit cd914d8 (12 Jan 2016) by Elia Pinto (devzero2000).
(Merged by Junio C Hamano -- gitster -- in commit e572fef, 22 Jan 2016)

From Git 2.8 onwards, it is all $(...), no more `...`.

Community
  • 1
  • 1
VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
  • 5
    `$()` is also POSIX-specified -- a quote that describes backticks as "POSIX-supported" in such a way to imply that this is unique to them is misleading. It's only (1970s-era) pre-POSIX Bourne where backticks are the only supported syntax. – Charles Duffy Mar 30 '17 at 15:09
29

When the older back-tick form is used, backslash retains its literal meaning except when followed by $, `, or \. The first back-tick not preceded by a backslash terminates the command substitution.

When using the newer $(command) form, all characters between the parentheses make up the command; none are treated specially.

Both forms can be nested, but the back-tick variety requires the following form.

`echo \`foo\`` 

As opposed to:

$(echo $(foo))
ocodo
  • 29,401
  • 18
  • 105
  • 117
6

There is little difference, except for what unescaped characters you can use inside of the command. You can even put `...` commands inside $(...) ones (and vice versa) for a more complicated two-level-deep command substitution.

There is a slightly different interpretation of the backslash character/operator. Among other things, when nesting `...` substitution commands, you must escape the inner ` characters with \, whereas with $() substition it understands the nesting automatically.

DigitalRoss
  • 143,651
  • 25
  • 248
  • 329
1

"What's the difference if any between the two methods?"

Make attention to this behaviour:

A="A_VARIABLE"
echo "$(echo "\$A")"
echo "`echo "\$A"`"

You will get these results:

$A
A_VARIABLE

 

Adrian
  • 1,558
  • 1
  • 13
  • 31
Hiro
  • 56
  • 5
  • `echo "$(echo "\$A")"` should be compared with `echo "\`echo \"\$A\"\`"`. The output is the same. – FooF Sep 08 '20 at 08:43
  • I tried your notation now, still output is $A and A_VARIABLE. – Hiro Sep 09 '20 at 09:49
  • 1
    Difference is that $() don't translating escaped (\$A) variables and ` ` translating. Way is to double escape variable inside ` ` - `\\$A`. Conclusion for this is that you can't simply replace ` ` with $( ). Is need to check it inside for escape characters. (GNU bash, version 4.2.46(2)-release (x86_64-redhat-linux-gnu)) – Hiro Sep 09 '20 at 09:52