Run two commands in case of || or &&
Solution 1:
Using parens puts the commands in a subshell which is not always what you want. Alternatively, use curly braces:
command && echo "Ok, continuing" || { echo "Check internet connection"; exit 1; }
The trick here is that, unlike parens, the final command in braces must be followed by ;
.
Why a semicolon or newline is required
A curly brace is a valid argument to a command. For example, here is a curly brace as an argument to echo
:
$ echo }
}
Consequently, if the shell sees:
{ command1; command2 }
The shell interprets command1 as having no arguments and command2 as having one argument consisting of the character }
. A curly brace }
is only interpreted as closing a grouping if it follows a semicolon or newline. To make the above work:
{ command1; command2; }
Subshells and the difference between {...}
and (...)
Observe that the following sets x
to 10 but that that setting is forgotten before the echo
command runs:
$ x=0; false || ( echo Hello; x=10 )
Hello
$ echo $x
0
With curly braces, by contrast, the setting of x=10
is remembered:
$ x=0; false || { echo Hello; x=10; }
Hello
$ echo $x
10
The difference is because variable assignments in a subshell do not survive after the subshell completes.
Documentation
From man bash
:
(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.
{ list; }
list is simply executed in the current shell environment. list must be terminated with a newline or semicolon. This is known as a group command. The return status is the exit status of list. Note that unlike the metacharacters ( and ), { and } are reserved words and must occur where a reserved word is permitted to be recognized. Since they do not cause a word break, they must be separated from list by whitespace or another shell metacharacter.
[Emphasis added]