Linguistically, you can think of statement1 && statement2
by itself as saying "execute statement1, and if its exit status is 0, then execute statement2." The other statement1 || statement2
syntax by itself translates to "execute statement1, and if its exit status is not 0, then execute statement2."
These operators are primarily intended for use within single conditions of if-constructs. But, they also have use in other places to compress confusing syntax.
The semicolon, ;
, is just Bash's standard statement separator (e.g. it allows you to put two statements on the same line and run the 2nd immediately after the 1st, barring circumstances irrelevant to this explanation). Any statement after the semicolon will be interpreted nomatter the result (true/false) of the previous return value.
If A fails, then run B, but if A succeeds, then run C (How can I do
this with "||" ";" and/or "&&"?)
A && C || B
Let's test it out:
john@mypc:~/test$ ls
file-A.txt file-B.txt file-C.txt
john@mypc:~/test$ cat file-A.txt && cat file-C.txt || cat file-B.txt
file A content
file C content
john@mypc:~/test$ rm file-A.txt
john@mypc:~/test$ ls
file-B.txt file-C.txt
john@mypc:~/test$ cat file-A.txt && cat file-C.txt || cat file-B.txt
cat: file-A.txt: No such file or directory
file B content
john@mypc:~/test$
As you can see, file B's contents were only printed when printing file A failed. Before we deleted file A, its content printed successfully and only file C's content printed afterward.
On the other hand, ;
symbols are agnostic of the previous return code. For example given three commands X, Y, Z, X && Y && Z
will not execute statement Z if Y (or X) returns a non-zero exit code, whereas (for all intents and purposes) X ; Y ; Z
will execute all three independent of command X and Y's exit codes.