558

I am a little bit confused on what do these operators do differently when used in bash (brackets, double brackets, parenthesis and double parenthesis).

[[ , [ , ( , ((

I have seen people use them on if statements like this:

if [[ condition ]]

if [ condition ]

if ((condition))

if (condition)

RetroCode
  • 5,729
  • 3
  • 10
  • 8

7 Answers7

632

In Bourne-like shells, an if statement typically looks like

if
   command-list1
then
   command-list2
else
   command-list3
fi

The then clause is executed if the exit code of the command-list1 list of commands is zero. If the exit code is nonzero, then the else clause is executed. command-list1 can be simple or complex. It can, for example, be a sequence of one or more pipelines separated by one of the operators ;, &, &&, || or newline. The if conditions shown below are just special cases of command-list1:

  1. if [ condition ]

    [ is another name for the traditional test command. [ / test is a standard POSIX utility. All POSIX shells have it builtin (though that's not required by POSIX²). The test command sets an exit code and the if statement acts accordingly. Typical tests are whether a file exists or one number is equal to another.

  2. if [[ condition ]]

    This is a new upgraded variation on test¹ from ksh that bash, zsh, yash, busybox sh also support. This [[ ... ]] construct also sets an exit code and the if statement acts accordingly. Among its extended features, it can test whether a string matches a wildcard pattern (not in busybox sh).

  3. if ((condition))

    Another ksh extension that bash and zsh also support. This performs arithmetic. As the result of the arithmetic, an exit code is set and the if statement acts accordingly. It returns an exit code of zero (true) if the result of the arithmetic calculation is nonzero. Like [[...]], this form is not POSIX and therefore not portable.

  4. if (command)

    This runs command in a subshell. When command completes, it sets an exit code and the if statement acts accordingly.

    A typical reason for using a subshell like this is to limit side-effects of command if command required variable assignments or other changes to the shell's environment. Such changes do not remain after the subshell completes.

  5. if command

    command is executed and the if statement acts according to its exit code.

Note that [ ... ] and [[ ... ]] require whitespace around them, while (...) and ((...)) do not.


¹ though not really a command but a special shell construct with its own separate syntax from that of normal command, and varying significantly between shell implementations

² POSIX does require that there be a standalone test and [ utilities on the system however, though in the case of [, several Linux distributions have been known to be missing it.

ilkkachu
  • 138,973
John1024
  • 74,655
  • 69
    Thanks for including the 5th option. That's key to understanding how this actually works and is surprisingly underutilized. – chicks Aug 30 '16 at 19:32
  • 13
    Note that [ is actually a binary, not a internal command or symbol. Generally lives in /bin. – Julien R. Sep 03 '16 at 12:17
  • 21
    @JulienR. actually [ is a built in, as is test. There are binary versions available for compatibility reasons. Check out help [ and help test. – OldTimer Sep 20 '16 at 04:23
  • 22
    Worth noting that while (( isnt POSIX, $(( i.e. arithmetic expansion is and it's easy to confuse them. Often a workaround is to use something like [ $((2+2)) -eq 4 ] to make use of arithmetic in conditinal statements – Sergiy Kolodyazhnyy Nov 30 '17 at 18:10
  • How to have fun printing new lines: if echo; then echo; fi. – adentinger Feb 18 '18 at 01:53
  • It is not compatible across shell interpreters. If ou write a bash script, [[...]] and ((...)) are compatible for all systems. And in many guides, [[...]] is favored over [...]. – Wiimm Feb 05 '19 at 09:31
  • 9
    I wish I could up-vote this answer more than once. Perfect explanation. – Anthony Gatlin Oct 09 '19 at 11:33
  • 1
    Why would I use if [ condition ] rather than if condition? – Cameron Hudson Jan 15 '20 at 16:54
  • 4
    @CameronHudson If condition is a valid test condition, such as "$n" -gt 2, then use if [ condition ]. If, instead of a condition, you have a command, then use if command. – John1024 Jan 15 '20 at 18:07
  • @John1024 do you mean this? => when the condition to be evaluated is a command, use if command. When the condition is something to be evaluated as true or false, use if [command]. – EAmez Feb 07 '20 at 10:37
  • 1
    @EAmez I was distinguishing between a command, such as grep -q Error logfile, and a valid test condition, such as "$n" -gt 2. The shell uses if command but if [ condition ]. – John1024 Feb 07 '20 at 19:45
  • Thanks. For if [ ... ], [ is test, then what is ]? – Helin Wang Jan 05 '21 at 04:08
  • 2
    @HelinWang The ] is sometimes called syntactic sugar. It's purpose is to make the [ ... ] expression "easier to read or to express." In other words, when invoked as [, test requires that the last argument to the command must be ]. The reason is that a final ] makes the command look 'nicer.' – John1024 Jan 09 '21 at 23:16
  • 2
    Great answer! It should be part of the official document. The Bash if semantic is so different from those in other usual programming languages. – smwikipedia Sep 21 '21 at 02:59
  • This is great, but you could also mention spaces! For some of these constructs, they are required. – Zachary Vance Dec 07 '23 at 13:22
158
  • (…) parentheses indicate a subshell. What's inside them isn't an expression like in many other languages. It's a list of commands (just like outside parentheses). These commands are executed in a separate subprocess, so any redirection, assignment, etc. performed inside the parentheses has no effect outside the parentheses.
    • With a leading dollar sign, $(…) is a command substitution: there is a command inside the parentheses, and the output from the command is used as part of the command line (after extra expansions unless the substitution is between double quotes, but that's another story).
  • { … } braces are like parentheses in that they group commands, but they only influence parsing, not grouping. The program x=2; { x=4; }; echo $x prints 4, whereas x=2; (x=4); echo $x prints 2. (Also braces being keywords need to be delimited and found in command position (hence the space after { and the ; before }) whereas parentheses don't. That's just a syntax quirk.)
    • With a leading dollar sign, ${VAR} is a parameter expansion, expanding to the value of a variable, with possible extra transformations. The ksh93 shell also supports ${ cmd;} as form of command substitution that doesn't spawn a subshell.
  • ((…)) double parentheses surround an arithmetic instruction, that is, a computation on integers, with a syntax resembling other programming languages. This syntax is mostly used for assignments and in conditionals. This only exists in ksh/bash/zsh, not in plain sh.
    • The same syntax is used in arithmetic expressions $((…)), which expand to the integer value of the expression.
  • [ … ] single brackets surround conditional expressions. Conditional expressions are mostly built on operators such as -n "$variable" to test if a variable is empty and -e "$file" to test if a file exists. Note that you need a space around each operator (e.g. [ "$x" = "$y" ], not [ "$x"="$y" ]), and a space or a character like ; both inside and outside the brackets (e.g. [ -n "$foo" ], not [-n "$foo"]).
  • [[ … ]] double brackets are an alternate form of conditional expressions in ksh/bash/zsh with a few additional features, for example you can write [[ -L $file && -f $file ]] to test if a file is a symbolic link to a regular file whereas single brackets require [ -L "$file" ] && [ -f "$file" ]. See Why does parameter expansion with spaces without quotes works inside double brackets [[ but not single brackets [? for more on this topic.

In the shell, every command is a conditional command: every command has a return status which is either 0 indicating success or an integer between 1 and 255 (and potentially more in some shells) indicating failure. The [ … ] command (or [[ … ]] syntax form) is a particular command which can also be spelled test … and succeeds when a file exists, or when a string is non-empty, or when a number is smaller than another, etc. The ((…)) syntax form succeeds when a number is nonzero. Here are a few examples of conditionals in a shell script:

  • Test if myfile contains the string hello:

    if grep -q hello myfile; then …
    
  • If mydir is a directory, change to it and do stuff:

    if cd mydir; then
      echo "Creating mydir/myfile"
      echo 'some content' >myfile
    else
      echo >&2 "Fatal error. This script requires mydir to exist."
    fi
    
  • Test if there is a file called myfile in the current directory:

    if [ -e myfile ]; then …
    
  • The same, but also including dangling symbolic links:

    if [ -e myfile ] || [ -L myfile ]; then …
    
  • Test if the value of x (which is assumed to be numeric) is at least 2, portably:

    if [ "$x" -ge 2 ]; then …
    
  • Test if the value of x (which is assumed to be numeric) is at least 2, in bash/ksh/zsh:

    if ((x >= 2)); then …
    
  • 1
    Note that single bracket supports the -a instead of &&, so one can write: [ -L $file -a -f $file ], which is the same number of characters within the brackets without the extra [ and ]... – Alexis Wilke Aug 27 '16 at 23:34
  • 9
    @AlexisWilke The operators -a and -o are problematic because they can lead to incorrect parses if some of the operands involved look like operators. That's why I don't mention them: they have zero advantage and don't always work. And never write unquoted variable expansions without a good reason: [[ -L $file -a -f $file ]] is fine but with single brackets you need [ -L "$file" -a -f "$file" ] (which is ok e.g. if $file always starts with / or ./). – Gilles 'SO- stop being evil' Aug 27 '16 at 23:38
  • Note that it's [[ -L $file && -f $file ]] (no -a with the [[...]] variant). – Stéphane Chazelas Nov 30 '17 at 15:25
  • The part about braces being keywords is important. It's what allows you to do things like: { task1 && task2 && task3 && echo "Success!"; } || { echo "One of the tasks failed!"; exit 1; } in a larger script. If you use parentheses, exit 1 will just exit out of a subshell and any surrounding script will keep running. Without the ending semicolon in each set of braces, you'll get "Unexpected end of file". – Jemenake May 18 '23 at 22:54
  • The examples make the better answer. – galaxis Sep 12 '23 at 10:48
59

[ vs [[

This answer will cover the [ vs [[ subset of the question.

Some differences on Bash 4.3.11:

  • POSIX vs Bash extension:

  • regular command vs magic

    • [ is just a regular command with a weird name.

      ] is just the last argument of [.

      Ubuntu 16.04 actually has an executable for it at /usr/bin/[ provided by coreutils, but the bash built-in version takes precedence.

      Nothing is altered in the way that Bash parses the command.

      In particular, < is redirection, && and || concatenate multiple commands, ( ) generates subshells unless escaped by \, and word expansion happens as usual.

    • [[ X ]] is a single construct that makes X be parsed magically. <, &&, || and () are treated specially, and word splitting rules are different.

      There are also further differences like = and =~.

    In Bashese: [ is a built-in command, and [[ is a keyword: https://askubuntu.com/questions/445749/whats-the-difference-between-shell-builtin-and-shell-keyword

  • <

  • && and ||

    • [[ a = a && b = b ]]: true, logical and
    • [ a = a && b = b ]: syntax error, && parsed as an AND command separator cmd1 && cmd2
    • [ a = a ] && [ b = b ]: POSIX reliable equivalent
    • [ a = a -a b = b ]: almost equivalent, but deprecated by POSIX because it is insane and fails for some values of a or b like ! or ( which would be interpreted as logical operations
  • (

    • [[ (a = a || a = b) && a = b ]]: false. Without ( ), would be true because [[ && ]] has greater precedence than [[ || ]]
    • [ ( a = a ) ]: syntax error, () is interpreted as a subshell
    • [ \( a = a -o a = b \) -a a = b ]: equivalent, but (), -a, and -o are deprecated by POSIX. Without \( \) would be true because -a has greater precedence than -o
    • { [ a = a ] || [ a = b ]; } && [ a = b ] non-deprecated POSIX equivalent. In this particular case however, we could have written just: [ a = a ] || [ a = b ] && [ a = b ] because the || and && shell operators have equal precedence unlike [[ || ]] and [[ && ]] and -o, -a and [
  • word splitting and filename generation upon expansions (split+glob)

    • x='a b'; [[ $x = 'a b' ]]: true, quotes not needed
    • x='a b'; [ $x = 'a b' ]: syntax error, expands to [ a b = 'a b' ]
    • x='*'; [ $x = 'a b' ]: syntax error if there's more than one file in the current directory.
    • x='a b'; [ "$x" = 'a b' ]: POSIX equivalent
  • =

    • [[ ab = a? ]]: true, because it does pattern matching (* ? [ are magic). Does not glob expand to files in current directory.
    • [ ab = a? ]: a? glob expands. So may be true or false depending on the files in the current directory.
    • [ ab = a\? ]: false, not glob expansion
    • = and == are the same in both [ and [[, but == is a Bash extension.
    • case ab in (a?) echo match; esac: POSIX equivalent
    • [[ ab =~ 'ab?' ]]: false, loses magic with '' in Bash 3.2 and above and provided compatibility to bash 3.1 is not enabled (like with BASH_COMPAT=3.1)
    • [[ ab? =~ 'ab?' ]]: true
  • =~

    • [[ ab =~ ab? ]]: true, POSIX extended regular expression match, ? does not glob expand
    • [ a =~ a ]: syntax error. No bash equivalent.
    • printf 'ab\n' | grep -Eq 'ab?': POSIX equivalent (single line data only)
    • awk 'BEGIN{exit !(ARGV[1] ~ ARGV[2])}' ab 'ab?': POSIX equivalent.

Recommendation: always use []

There are POSIX equivalents for every [[ ]] construct I've seen.

If you use [[ ]] you:

  • lose portability
  • force the reader to learn the intricacies of another bash extension. [ is just a regular command with a weird name, no special semantics are involved.

Thanks to Stéphane Chazelas for important corrections and additions.

Ciro Santilli OurBigBook.com
  • 18,092
  • 4
  • 117
  • 102
  • @StéphaneChazelas thanks for the info! I've addedexpr to the answer. The term "Bash extension" is not meant to imply Bash was the first shell to add some syntax, learning POSIX sh vs Bash is already enough to drive me crazy. – Ciro Santilli OurBigBook.com Feb 05 '19 at 09:11
  • 3
    See man test if you tried man [ and got lost. That will explain the POSIX variant. – Jonathan Komar Jun 04 '19 at 07:25
  • 2
    Correction: ] is an argument to the [ command, but it doesn't prevent further arguments from being used. ] must be the last argument to [, but it can also occur as part of the test expression. For example, if [ "$foo" = ] ]; then will test whether the variable foo is set to "]" (as will if [ ] = "$foo" ]; then). – Gordon Davisson Jan 05 '21 at 05:07
  • @GordonDavisson thanks, I didn't know that, fixed. – Ciro Santilli OurBigBook.com Jan 06 '21 at 09:01
  • It seems to me that using [[ (instead of [) is well worth losing portability in most cases. Anything to avoid excess escaping increases shell readability, and hence reduces bugs. Shell code is already so muddled up that there are routinely errors centered around whether or not something needs one backslash or two, and anything that mitigates the likelihood of saying "WTF just happened here" is a win. – tgm1024--Monica was mistreated Jan 13 '21 at 00:04
  • 1
    @tgm1024--Monicawasmistreated yes, that is also a valid consideration. – Ciro Santilli OurBigBook.com Jan 13 '21 at 08:32
  • 1
    So impressive ... – jfernandz Mar 02 '22 at 19:00
  • Thanks for the great summary of the differences (although I disagree with the recommendation.) Another important difference: the arguments to binary operators such as -eq are evaluated as arithmetic expressions when used with [[. E.g. try [[ 2 -eq "1 + 1" ]] or [[ 10 -eq 0xA ]]. – dc46and2 Apr 12 '22 at 17:38
27

From the bash documentation:

(list) list is executed in a subshell environment (see COMMAND EXECUTION ENVIRONMENT below). Variable assignments and builtin commands that affect the shell's environment do not remain in effect after the command completes. The return status is the exit status of list.

In other words, you make sure that whatever happens in 'list' (like a cd) has no effect outside of the ( and ). The only thing that will leak is the exit code of the last command or with set -e the first command that generates an error (other than a few such as if, while, etc.)

((expression)) The expression is evaluated according to the rules described below under ARITHMETIC EVALUATION. If the value of the expression is non-zero, the return status is 0; otherwise the return status is 1. This is exactly equivalent to let "expression".

This is a bash extension allowing you to do math. This is somewhat similar to using expr without all the limitations of expr (such as having spaces everywhere, escaping *, etc.)

[[ expression ]] Return a status of 0 or 1 depending on the evaluation of the conditional expression expression. Expressions are composed of the primaries described below under CONDITIONAL EXPRESSIONS. Word splitting and pathname expansion are not performed on the words between the [[ and ]]; tilde expansion, parameter and variable expansion, arithmetic expansion, command substitution, process substitution, and quote removal are performed. Conditional operators such as -f must be unquoted to be recognized as primaries.

When used with [[, the < and > operators sort lexicographically using the current locale.

This offers an advanced test to compare strings, numbers, and files a bit like test offers, but more powerful.

[ expr ] Return a status of 0 (true) or 1 (false) depending on the evaluation of the conditional expression expr. Each operator and oper and must be a separate argument. Expressions are composed of the primaries described above under CONDITIONAL EXPRESSIONS. test does not accept any options, nor does it accept and ignore an argument of -- as signifying the end of options.

[...]

This one calls test. Actually, in the old days, [ was a symbolic link to test. It works the same way and you have the same limitations. Since a binary knows the name with which it was started, the test program knows when it was started as [ and it can ignore its last parameter, which is expected to be ]. Fun Unix tricks.

Note that in case of bash, [ and test are built-in functions (as mentioned in a comment), yet pretty much the same limitations apply.

Alexis Wilke
  • 2,857
  • 1
    Though test and [ are of course builtin commands in Bash, but it's likely that an external binary exists too. – ilkkachu Aug 27 '16 at 19:12
  • 1
    The external binary for [ is not a symbolic link to test on most modern systems. – Random832 Aug 27 '16 at 19:16
  • @Random832 Ah... Interest, not only [ is not a symbolic link, it's not the same size as test! So it is its own beast altogether. – Alexis Wilke Aug 27 '16 at 19:17
  • They're the same size on OSX. I think the difference on GNU is that [ supports --help and --version, so the text for those options is included, and test does not. command [ --help|wc -c shows the help text is 3 kb. – Random832 Aug 27 '16 at 19:20
  • 1
    Somehow, I find it amusing that they bother to create two separate binaries, which both have just exactly what they need, instead of just combining them and adding a couple of conditionals. Though actually strings /usr/bin/test shows it has the help text too, so I don't know what to say. – ilkkachu Aug 27 '16 at 19:50
  • @Random832 The difference is [ needs to look for a closing ] while test does not. Of course a purposely designed single binary can handle both behaviors but my understanding is POSIX doesn't require [ to exist as a file. Its name is not even in the portable file name character set. – jlliagre Aug 27 '16 at 23:20
  • @jlliagre It does require it to exist as a file (hell, it requires cd to exist as a file); the purpose of the portable filename character set doesn't preclude the standard requiring a specific file with a specific name containing a character set outside it. Anyway, modern systems tend to lean away from the "single binary handling different behaviors depending on argv[0] concept - There's a rationale for why it's a considered bad (and why gnu coreutils doesn't do it, not only for [/test, but also ls/dir/vdir) EDIT: https://www.gnu.org/prep/standards/html_node/User-Interfaces.html – Random832 Aug 28 '16 at 02:48
  • 2
    @Random832 I get your point about the GNU rationale to avoid unexpected arg0 behavior but about POSIX requirements, I wouldn't be so affirmative. While the test command is obviously required to exist as a standalone file based command by the standard, nothing in it states its [ variant need to be implemented that way too. For example, Solaris 11 doesn't provide any [ executable but is nevertheless fully compliant with the POSIX standards – jlliagre Aug 28 '16 at 04:00
  • @jlliagre See the last paragraph here. If that's true it's probably a bug in whatever test suite was used to certify its compliance. (Note: Yes, it is permitted for it to exist as a symlink or hardlink and not a separate and distinct file, but it sounded like you were saying it's not required to exist, and doesn't exist, as any kind of file at all - there's no language in the standard treating [ differently from test for the purpose of this requirement) – Random832 Aug 28 '16 at 04:11
  • @Random832 I know quite well that paragraph ( see http://unix.stackexchange.com/questions/38808/why-is-cd-not-a-program/38819#38819 ) but IMHO there is nothing in this case Solaris is violating. The test utility is definitely provided as a standalone executable. Nowhere is written it requires its variant to be that way, and the fact it doesn't conform with the first and second guidelines stated here http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap12.html#tag_12_02 likely doesn't help supporting the idea. – jlliagre Aug 28 '16 at 04:50
  • @Random832 Of course, you are free to disagree and file a bug. Here is the link http://austingroupbugs.net/main_page.php . Keep us informed if you do ! – jlliagre Aug 28 '16 at 04:50
  • 3
    (exit 1) has an effect outside of the parentheses. – Alexander Feb 10 '18 at 08:23
  • 1
    @Alexander, I applied a correction. Thank you for pointing that out. – Alexis Wilke Feb 10 '18 at 21:49
  • 1
    Correction: [ does not parse parameters until it finds a parameter ]; instead, it checks that its last argument is "]", and then ignores it while parsing the rest of its arguments as a test expression. This means that "]" can occur in the middle of the expression as well as the end. For example, if [ "$foo" = ] ]; then will test whether the variable foo is set to "]" (as will if [ ] = "$foo" ]; then). – Gordon Davisson Jan 05 '21 at 05:12
  • @GordonDavisson, indeed. I made an edit accordingly. – Alexis Wilke Jan 05 '21 at 15:54
18

Some examples:

Traditional test:

foo="some thing"
# check if value of foo is not empty
if [ -n "$foo" ] ; then... 
if test -n "$foo" ; then... 

test and [ are commands like any others, so the variable is split into words unless it's in quotes.

New-style test

[[ ... ]] is a (newer) special shell construct, which works a bit differently, the most obvious thing being that it doesn't word-split variables:

if [[ -n $foo ]] ; then... 

Some documentation on [ and [[ here.

Arithmetic test:

foo=12 bar=3
if (( $foo + $bar == 15 )) ; then ...  

"Normal" commands:

All of the above act like normal commands, and if can take any command:

# grep returns true if it finds something
if grep pattern file ; then ...

Multiple commands:

Or we can use multiple commands. Wrapping a set of commands in ( ... ) runs them in subshell, creating a temporary copy of the shell's state (working directory, variables). If we need to run some program temporarily in another directory:

# this will move to $somedir only for the duration of the subshell 
if ( cd $somedir ; some_test ) ; then ...

# while here, the rest of the script will see the new working
# directory, even after the test
if cd $somedir ; some_test ; then ...
ilkkachu
  • 138,973
12

Special characters:

Char. Description
Whitespace — this is a tab, newline, vertical tab, form feed, carriage return, or space. Bash uses whitespace to determine where words begin and end. The first word is the command name and additional words become arguments to that command.
$ Expansion — introduces various types of expansion: parameter expansion (e.g. $var or ${var}), command substitution (e.g. $(command)), or arithmetic expansion (e.g. $((expression))).
'' Single quotes — protect the text inside them so that it has a literal meaning. With them, generally any kind of interpretation by Bash is ignored: special characters are passed over and multiple words are prevented from being split.
"" Double quotes — protect the text inside them from being split into multiple words or arguments, yet allow substitutions to occur; the meaning of most other special characters is usually prevented.
\ Escape — (backslash) prevents the next character from being interpreted as a special character. This works outside of quoting, inside double quotes, and generally ignored in single quotes.
# Comment — the # character begins a commentary that extends to the end of the line. Comments are notes of explanation and are not processed by the shell.
= Assignment -- assign a value to a variable (e.g. logdir=/var/log/myprog). Whitespace is not allowed on either side of the = character.
[[ ]] Test — an evaluation of a conditional expression to determine whether it is "true" or "false". Tests are used in Bash to compare strings, check the existence of a file, etc.
! Negate — used to negate or reverse a test or exit status. For example: ! grep text file; exit $?.
>, >>, < Redirection — redirect a command's output or input to a file.
| Pipe — send the output from one command to the input of another command. This is a method of chaining commands together. Example: echo "Hello beautiful." | grep -o beautiful.
; Command separator — used to separate multiple commands that are on the same line.
{ } Inline group — commands inside the curly braces are treated as if they were one command. It is convenient to use these when Bash syntax requires only one command and a function doesn't feel warranted.
( ) Subshell group — similar to the above but where commands within are executed in a subshell (a new process). Used much like a sandbox, if a command causes side effects (like changing variables), it will have no effect on the current shell.
(( )) Arithmetic expression — with an arithmetic expression, characters such as +, -, *, and / are mathematical operators used for calculations. They can be used for variable assignments like (( a = 1 + 4 )) as well as tests like if (( a < b )).
$(( )) Arithmetic expansion — Comparable to the above, but the expression is replaced with the result of its arithmetic evaluation. Example: echo "The average is $(( (a+b)/2 ))".
*, ? Globs -- "wildcard" characters which match parts of filenames (e.g. ls *.txt).
~ Home directory — the tilde is a representation of a home directory. When alone or followed by a /, it means the current user's home directory; otherwise, a username must be specified (e.g. ls ~/Documents; cp ~john/.bashrc .).
& Background -- when used at the end of a command, run the command in the background (do not wait for it to complete).

Deprecated special characters (recognized, but not recommended):

Char. Description
` ` Command substitution - use $( ) instead.
[ ] Test - an alias for the old test command. Commonly used in POSIX shell scripts. Lacks many features of [[ ]].
$[ ] Arithmetic expression - use $(( )) instead.

Source

muru
  • 72,889
Premraj
  • 2,542
0

Beware numeric comparisons. Quiz what is the output?

if ((10 > 2)); then echo 1; fi
if [[ 10 > 2 ]]; then echo 2; fi
if [ 10 -gt 2 ]; then echo 3; fi
if [[ 10 -gt 2 ]]; then echo 4; fi

answer: 1 3 4

Putting quotes around the numbers does not make any difference.