Why does parameter expansion with spaces without quotes work inside double brackets "[[" but not inside single brackets "["?

I'm perplexed with making use of solitary or double brackets. Consider this code:

dir="/home/mazimi/VirtualBox VMs"

if [[ -d ${dir} ]]; then
    echo "yep"

It functions flawlessly although the string has a room. Yet when I transform it to solitary brace:

dir="/home/mazimi/VirtualBox VMs"

if [ -d ${dir} ]; then
    echo "yep"

It claims:

./script.sh: line 5: [: /home/mazimi/VirtualBox: binary operator expected

When I transform it to:

dir="/home/mazimi/VirtualBox VMs"

if [ -d "${dir}" ]; then
    echo "yep"

It functions penalty. Can a person clarify what is taking place? When should I assign double quotes around variables like "${var}" to stop troubles brought on by rooms?

2022-06-06 19:08:10
Source Share
Answers: 3

For taking care of rooms and also empty|unique personalities in variables you need to constantly border them with double quotes. Establishing a correct IFS is an excellent technique also.

Advised: http://www.dwheeler.com/essays/filenames-in-shell.html

2022-06-06 19:23:41

The [ command is an average command. Although the majority of coverings give it as a constructed - in for performance, it complies with the covering is regular syntactic regulations. [ is specifically equal to test, other than that [ calls for a ] as its last argument and also test does not.

The double brackets [[ … ]] are unique syntax. They were presented in ksh (numerous years after [) due to the fact that [ can be frustrating to make use of appropriately and also [[ permits some new wonderful enhancements that make use of covering unique personalities. As an example, you can write

[[ $x = foo && $y = bar ]]

due to the fact that the whole conditional expression is analyzed by the covering, whereas [ $x = foo && $y = bar ] would certainly first be divided right into 2 commands [ $x = foo and also $y = bar ] divided by the && driver. In a similar way double brackets enable points like the pattern matching syntax, as an example [[ $x == a* ]] to test whether the value of x begins with a ; in solitary brackets this would certainly expand a* to the checklist of documents whose names begins with a in the existing directory site. Double brackets were first presented in ksh and also are just readily available in ksh, bash and also zsh.

Inside solitary brackets, you require to make use of double quotes around variable replacements, like in the majority of various other areas, due to the fact that they are simply debates to a command (which takes place to be the [ command). Inside double brackets, you do not require double quotes, due to the fact that the covering does not do word splitting or globbing: it is analyzing a conditional expression, not a command.

An exemption though is [[ $var1 = "$var2" ]] where you require the quotes if you intend to do a byte - to - byte string contrast, or else, $var2 would certainly be a pattern to match $var1 versus.

One point you can not perform with [[ … ]] is make use of a variable as a driver. As an example, this is flawlessly lawful (yet hardly ever valuable):

if [ -n "$reverse_sort" ]; then op=-gt; else op=-lt; fi
if [ "$x" "$op" "$y" ]; then …

In your instance

dir="/home/mazimi/VirtualBox VMs"
if [ -d ${dir} ]; then …

the command inside the if is [ with the 4 debates -d, /home/mazimi/VirtualBox, VMs and also ]. The covering analyzes -d /home/mazimi/VirtualBox and afterwards does not recognize what to do with VMs. You would certainly require to stop word splitting on ${dir} to get a well - created command.

Usually talking, constantly make use of double quotes around variable and also command replacements unless you recognize you intend to execute word splitting and also globbing on the outcome. The major areas where it is secure not to make use of the double quotes are:

  • in an assignment: foo=$bar (yet keep in mind that you do require the double quotes in export "foo=$bar" or in array jobs like array=("$a" "$b")) ;
  • in a case declaration: case $foo in … ;
  • inside double brackets other than on the right-hand man side of the = or == driver (unless you do desire pattern matching): [[ $x = "$y" ]]

In all of these, it is proper to make use of double quotes, so you could too miss the innovative regulations and also make use of the quotes regularly.

2022-06-06 19:20:34

The solitary brace [ is in fact a pen name for the test command, it is not syntax.

Among the disadvantages (of several) of the solitary brace is that if several of the operands it is attempting to review return a vacant string, it will certainly whine that it was anticipating 2 operands (binary). This is why you see individuals do [ x$foo = x$blah ], the x assures that the operand will certainly never ever review to a vacant string.

The double brace [[ ]], on the various other hand, is syntax and also is far more qualified than [ ]. As you figured out, it does not have the "missing operand" concern and also it additionally permits even more C - like syntax with >, <, >=, <=, !=, ==, &&, || drivers.

My referral is the following: If your interpreter is #!/bin/bash, after that constantly make use of [[ ]]

It is necessary to keep in mind that [[ ]] is not sustained by all POSIX coverings, nonetheless several coverings do sustain it such as zsh and also ksh along with bash

2022-06-06 19:20:05