Use double brackets (see Why does parameter expansion with spaces without quotes work inside double brackets "[[" but not inside single brackets "["?). Use the &&
and ||
double-bracket condition operators instead of the -a
and -o
test/single-bracket condition operators. This works in bash, also in ksh and zsh, but not in plain sh.
if [[ ( -e file.txt && -r file.txt ) || ( -e file2.txt && -r file2.txt ) ]]; then
Alternatively, with single brackets, use [
around single checks, use the &&
and ||
shell operators outside of brackets instead of using the -a
and -o
test operators inside brackets, and use { … }
for grouping (see Difference between parentheses and braces in terminal?). This works in any sh-style shell.
if { [ -e file.txt ] && [ -r file.txt ]; } ||
{ [ -e file2.txt ] && [ -r file2.txt ]; }
then …
Alternatively, you can use \(
and \)
(or any other way of quoting the parentheses) inside single brackets (again, see Why does parameter expansion with spaces without quotes work inside double brackets "[[" but not inside single brackets "["? for an explanation). However this can cause the condition to be parsed incorrectly if a file name looks like a test operator ((
, =
, -e
, …).
-e
tests, since-r
includes the test for existence. So justif [ -r file.txt ] && [ -r file2.txt ]; then ...