5

Some shell scripts I have come across use the following syntax when defining variables:

file_list_1=$(echo "list.txt")

or

file_list_2=$(find ./)

I would have used:

file_list_1="list.txt"

and

file_list_2=`find ./`

I'm not sure which if any of the above are better or safer. What is the benefit of using the syntax x=$( ) when setting a variable?

Rui F Ribeiro
  • 56,709
  • 26
  • 150
  • 232
Chris R
  • 53

2 Answers2

9

From the manual (man bash):

$(command)  or  `command`

Bash performs the expansion by executing command 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).

When the old-style backquote form of substitution is used, backslash retains its literal meaning except when followed by $, `, or \. The first backquote not preceded by a backslash terminates the command substitution. When using the $(command) form, all characters between the parentheses make up the command; none are treated specially.

The POSIX standard defines the $() form of command substitution. $() allows nested commands and looks better (legibility). It should be available on all Bourne shells.

You can read more on IEEE Std 1003.1, Shell Command Language, Section 2.6.3 Command Substitution.

At least one Unix, AIX, has documented that backticks are obsolete. From that link:

Although the backquote syntax is accepted by ksh, it is considered obsolete by the X/Open Portability Guide Issue 4 and POSIX standards. These standards recommend that portable applications use the $(command) syntax.

However, /bin/sh does not have to be POSIX compliant. So there is still sometimes a case for backticks in the real world, as @Jeight points out.

Christopher
  • 15,911
  • Is there any point in using command substitution to define a variable statically, as in file_list_1=$(echo "list.txt")? Maybe for special characters? – Chris R May 21 '15 at 23:53
  • I take it you don't work with older UNIX systems that often? Obsolete maybe by modern standards yes. – Jeight May 22 '15 at 00:30
  • Sorry. I didn't mean to come across so harsh. I just have to create backward compatible scripts everyday. This is by far the better and more complete answer. – Jeight May 22 '15 at 00:38
  • @Jeight No - no. not at all! I knew exactly what you meant in your answer. I did not down-vote you. U&L SE seems brutal sometimes, but it is much less of a goat rodeo than "the other" SE site. :) I am actually waiting for a better answer, because I know there are people here who could answer better. – Christopher May 22 '15 at 00:44
  • (I don't have the reputation to upvote but I do appreciate the help from both of you, and @G-Man of course!) – Chris R May 22 '15 at 01:10
  • 1
    @Christopher: You say “The POSIX standard defines the $() form of command substitution. $() allows nested commands”.  True.  Also, the POSIX standard defines the \…`` form of command substitution, and \…`` allows nested commands (cmd₃ … `cmd₂ … \`cmd₁ …\` …` …). – G-Man Says 'Reinstate Monica' May 22 '15 at 03:40
  • 1
    @G-Man; With backtics nesting requires escapes, as you've showed. - How would another level of nesting be implemented? How would consistent double-quoting on each level be implemented? - Short answer; use $(...) instead. – Janis May 22 '15 at 06:32
  • @Christopher; You are technically right that /bin/sh may be an old bourne shell (in the 1970's and early 1980's). But have you seen such systems in the past two decades? - Even in the 1990's the commercial systems (e.g. AIX, HP-UX) usually have sh linked to a ksh (ksh88), which was the base for POSIX and supported $(...). – Janis May 22 '15 at 06:36
  • @Janis IKR? No, I have never actually seen one, and I started in 92! – Christopher May 22 '15 at 10:57
1

It's a lot of personal preference. Using a backtick to signify a command would be more POSIX compatible with older systems. The $() is more modern and is easier to read for some people. I would personally never use file_list_1=$(echo "list.txt"). It seems to ugly and has no additional use.

Christopher
  • 15,911
Jeight
  • 2,603
  • That's not correct. – DisplayName May 21 '15 at 23:18
  • @DisplayName Really? Why don't you clarify? The answer from CHristopher is referring to bash, but what if you are using an older HPUX that uses sh or ksh... is $() POSIX compatible then? The only thing I left out was the litteral meaning of the entire command when using $() and not backticks. That can cause problems when you have nested quotations in your command. So like I said a lot of personal preference. – Jeight May 22 '15 at 00:07
  • I did mean all Bourne shells (ash, bash, dash, zsh, etc), not just the Bourne Again Shell (BASH). – Christopher May 22 '15 at 00:13
  • I understand, but you are talking modern shells, and I'm including older shells as well such as csh and sh. Look at http://www.efytimes.com/e1/creativenews.asp?edid=123101 – Jeight May 22 '15 at 00:26
  • So no, $() is not always POSIX compatible with older UNIX systems. – Jeight May 22 '15 at 00:27
  • 3
    @Jeight; There's confusing and misleading text above; "more POSIX compatible" ("more"?) and "is $() POSIX compatible" - those make no sense. - Note that $(...) is defined by POSIX, and any shell claiming to be POSIX compatible has to support it. Note also that older commercial Unixes (e.g. AIX, HP-UX) had ksh88, and ksh88 supported not only $(...) but invented it, and moreover, ksh88 was also the base for the POSIX definition. - The backtics, OTOH, have issues (see references), though, and are deprecated; there's no reason to use them, but reasons to abstain from using them. – Janis May 22 '15 at 06:24