Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Do I need to quote command substitutions?

According to the Google Shell Style Guide, I should:

Always quote strings containing variables, command substitutions, spaces or shell meta characters, unless careful unquoted expansion is required.

Maybe I am misinterpreting what they mean by "command substitutions", but I am wondering if there is any need to use quotes in the following example:

VAR="$(echo foo bar)"
like image 803
Joshua Spence Avatar asked Jun 20 '16 20:06

Joshua Spence


3 Answers

$(echo foo bar) is indeed a command substitution. In this specific example, you don't need double quotes because a variable assignment creates a “double quote context” for its right-hand side, so VAR=$(…) is equivalent to VAR="$(…)".

In bash, you don't need double quotes in export VAR=$(…) or declare VAR=$(…). But you do need the double quotes in some other sh implementations such as dash.

You do need double quotes in env VAR=$(…) somecommand, in make VAR=$(…), etc. It isn't the equal sign that makes the double quotes optional, it's the fact that the equal sign is parsed by the shell as an assignment.

There are a few other contexts where the double quotes are optional, but you can't go wrong with the simple rule: always use double quotes around variable and command substitutions unless you want the split+glob operator.

like image 120
Gilles 'SO- stop being evil' Avatar answered Oct 05 '22 22:10

Gilles 'SO- stop being evil'


EDIT: (A command substitution is $( ) and the back-tick almost-equivalent, so you're likely interpreting it correctly)

It will certainly not hurt to quote strings in general in shell scripts, unless you're actually relying on globbing etc. to take effect.

In this simple example, the double-quotes are certainly not needed, but for consistency I would probably add them.

If you instead have

VAR=$( echo $foo $bar )

... then I would certainly quote both variables and expression:

VAR="$( echo "$foo" "$bar" )"

especially if any of those variable contained external input or if you knew they had globbing-characters in them.

EDIT: As user @CharlesDuffy points out, the outer double-quotes here are still not needed. I would still add them to be consistent with other variable assignments that do need quoting.

like image 41
Kusalananda Avatar answered Oct 05 '22 22:10

Kusalananda


When not to quote a command substitution?

Answer: When you want the output of the command substitution to be treated as separate arguments.

Example:

We want to extract specific packets (packet numbers 1, 5, 10 and 20) from a .pcap file. The relevant command is the following:

editcap -r capture.pcap select.pcap 1 5 10 20

(Source to the command)

Now, we want to extract random packets from the file. To do that, we will use shuf from GNU Coreutils.

shuf -i 0-50 -n 4
8
24
20
31

The command above has generated 4 random numbers between 0 and 50.

Using it with editcap:

editcap -r source.pcap select.pcap "$(shuf -i 0-50 -n 4)"
editcap: The specified packet number "1
34
4
38" isn't a decimal number

As you can see, quoting the command substitution has resulted in the output string of the shuf to be treated as a single big string, including the newlines and whatnot as well. That is, putting quotes has resulted in the equivalent of the following command:

editcap -r source.pcap select.pcap "1
34
4
38"

Instead, we want Bash the chop the output of shuf and insert this chopped output as separate arguments to editcap. Omitting the quotes accomplishes that:

editcap -r source.pcap select.pcap $(shuf -i 0-50 -n 4)
like image 35
Utku Avatar answered Oct 05 '22 21:10

Utku