A co-worker claimed recently in a code review that the [[ ]] construct is to be preferred over [ ] in constructs like

if [ "`id -nu`" = "$someuser" ] ; then 
     echo "I love you madly, $someuser"
fi

He couldn't provide a rationale. Is there one?

share|improve this question
9  
Be flexible, sometimes allow yourself to listen an advice without requiring its deep explanation :) As for [[ with it the code is good and clear, but remember that day when you'll port your scriptworks on the system with default shell which is not bash or ksh, etc. [ is uglier, cumbersome, but works as AK-47 in any situation. – rook Aug 15 '13 at 20:20
35  
@rook You can listen to an advice without a deep explanation, sure. But when you request an explanation and don't get it, it's usually a red flag. "Trust, but verify" and all that. – Josip Rodin Apr 5 '16 at 11:07
up vote 364 down vote accepted

[[ has fewer surprises and is generally safer to use. But it is not portable - Posix doesn't specify what it does and only some shells support it (beside bash, i heard ksh supports it too). For example, you can do

[[ -e $b ]]

to test whether a file exists. But with [, you have to quote $b, because it splits the argument and expands things like "a*" (where [[ takes it literally). That has also to do with how [ can be an external program and receives its argument just normally like every other program (although it can also be a builtin, but then it still has not this special handling).

[[ also has some other nice features, like regular expression matching with =~ along with operators like they are known in C-like languages. Here is a good page about it: What is the difference between test, [ and [[ ? and Bash Tests

share|improve this answer
12  
Considering that bash is everywhere these days, I tend to think it's pretty damn portable. The only common exception for me is on busybox platforms - but you'd probably want to make a special effort for it anyways, given the hardware that it runs on. – guns Mar 21 '09 at 16:08
4  
@guns: Indeed. I'd suggest that your second sentence disproves your first; if you consider software development as a whole, "bash is everywhere" and "the exception is busybox platforms" are completely incompatible. busybox is widespread for embedded development. – BoundaryImposition Aug 21 '11 at 0:34
5  
@guns: Even if bash is installed on my box, it might not be executing the script (I might have /bin/sh symlinked to some dash-variant, as is standard on FreeBSD and Ubuntu). There's additional weirdness with Busybox, too: with standard compilation options nowadays, it parses [[ ]] but interprets it as meaning the same as [ ]. – dubiousjim May 31 '12 at 15:42
33  
@dubiousjim: If you use bash-only constructs (like this one), you should have #!/bin/bash, not #!/bin/sh. – Kundor Mar 4 '13 at 19:22
5  
That is why I make my scripts use #!/bin/sh but then switch them to use #!/bin/bash as soon as I rely on some BASH specific feature, to denote it is no longer Bourne shell portable. – anthony Feb 17 '16 at 6:20

[[ ]] has more features - I suggest you take a look at the Advanced Bash Scripting Guide for more info, specifically the extended test command section in Chapter 7. Tests.

Incidentally, as the guide notes, [[ ]] was introduced in ksh88 (the 1988 version of the Korn shell).

share|improve this answer
2  
This is far from a bashism, it was first introduced in the Korn shell. – Henk Langeveld Aug 30 '12 at 23:39
3  
@Thomas, the ABS is actually considered a very poor reference in many circles; while it has a great deal of accurate information, it tends to take very little care to avoid showcasing bad practices in its examples, and spent a great deal of its life unmaintained. – Charles Duffy Oct 4 '14 at 1:04
    
@CharlesDuffy thanks for your comment, can you name a good alternative. I'm not an expert in shell scripting, I am looking for a guide I can consult for writing a script about once every half year. – Thomas Oct 14 '14 at 7:30
3  
@Thomas, the Wooledge BashFAQ and associated wiki are what I use; they're actively maintained by the denizens of the Freenode #bash channel (who, while sometimes prickly, tend to care deeply about correctness). BashFAQ #31, mywiki.wooledge.org/BashFAQ/031, is the page directly relevant to this question. – Charles Duffy Oct 14 '14 at 13:18

From Which comparator, test, bracket, or double bracket, is fastest? (http://bashcurescancer.com)

The double bracket is a “compound command” where as test and the single bracket are shell built-ins (and in actuality are the same command). Thus, the single bracket and double bracket execute different code.

The test and single bracket are the most portable as they exist as separate and external commands. However, if your using any remotely modern version of BASH, the double bracket is supported.

share|improve this answer
5  
What's with the obsession of fastest in shell scripts? I want it most portable and couldn't care less about the improvement [[ might bring. But then, I'm an old school old fart :-) – Jens May 12 '12 at 17:11
1  
I think many shells prove builtin versions of [ and test even though external versions also exist. – dubiousjim May 31 '12 at 15:43
3  
@Jens in general I agree: the whole purpose of scripts is (was?) portability (otherwise, we'd code & compile, not script)... the two exceptions I can think of are: (1) tab completion (where completion scripts can get really long with lots of conditional logic); and (2) super-prompts (PS1=...crazy stuff... and/or $PROMPT_COMMAND); for these, I don't want any perceptible delay in the execution of the script. – michael_n Aug 1 '13 at 7:22

[[ ]] double brackets are unsuported under certain version of SunOS and totally unsuported inside function declarations by : GNU bash, version 2.02.0(1)-release (sparc-sun-solaris2.6)

share|improve this answer
1  
very true, and not at all inconsequential. bash portability across older versions must be considred. People say "bash is ubiquitous and portable, except for maybe (insert esoteric OS here)" -- but in my experience, solaris is one of those platforms where special attention must be paid to portability: not only to consider older bash versions on a newer OS, issues/bugs w/ arrays, functions, etc; but even utilities (used in the scripts) like tr, sed, awk, tar have oddities & peculiarities on solaris that you have to work-around. – michael_n Aug 1 '13 at 7:37
1  
you are so right... so much utilities non POSIX on Solaris, just look at the "df" output and arguments... Shame on Sun. Hopefully it's disappearing little by little (except in Canada). – scavenger Aug 3 '13 at 17:17
4  
Solaris 2.6 seriously? It was released in 1997 and ended support in 2006. I guess if you're still using that then you have other problems!. Incidentally it used Bash v2.02 which was the one that introduced double brackets so should work even on something as old as that. Solaris 10 from 2005 used Bash 3.2.51 and Solaris 11 from 2011 uses Bash 4.1.11. – peterh Oct 25 '13 at 7:15
1  
Re Script portability. On Linux systems there's generally only edition of each tool and that is the GNU edition. On Solaris you typically have a choice between a Solaris-native edition or the GNU edition (say Solaris tar vs GNU tar). If you depend on GNU specific extensions then you must state that in your script for it to be portable. On Solaris you do that by prefixing with "g", e.g. ` ggrep` if you want the GNU grep. – peterh Oct 25 '13 at 7:24

A typical situation where you cannot use [[ is in an autotools configure.ac script, there brackets has a special and different meaning, so you will have to use test instead of [ or [[ -- Note that test and [ are the same program.

share|improve this answer

In a nutshell, [[ is better because it doesn't fork another process. No brackets or a single bracket is slower than a double bracket because it forks another process.

share|improve this answer
4  
Test and [ are names for the same builtin command in bash. Try using type [ to see this. – alberge Jul 6 '11 at 17:56
    
@alberge, that's true, but [[, as distinct from [, is syntax interpreted by the bash command-line interpreter. In bash, try typing type [[. unix4linux is correct that although classic Bourne-shell [ tests fork off a new process to determine the truth value, the [[ syntax (borrowed from ksh by bash, zsh, etc) does not. – Tim Gilbert Nov 15 '12 at 19:47
    
@Tim, I'm not sure which Bourne shell you're talking about, but [ is built-in to Bash as well as Dash (the /bin/sh in all Debian-derived Linux distributions). – alberge Nov 18 '12 at 5:20
    
Oh, I see what you mean, that's true. I was thinking of something like, say, /bin/sh on older Solaris or HP/UX systems, but of course if you needed to be compatible with those you wouldn't be using [[ either. – Tim Gilbert Nov 28 '12 at 17:20

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.