bash if not multiple conditions without subshell?
You need to use { list;}
instead of (list)
:
if ! { [ -f file1 ] && [ -f file2 ] && [ -f file3 ]; }; then
: do something
fi
Both of them are Grouping Commands, but { list;}
executes commands in current shell environment.
Note that, the ;
in { list;}
is needed to delimit the list from }
reverse word, you can use other delimiter as well. The space (or other delimiter) after {
is also required.
To portably negate a complex conditional in shell, you must either apply De Morgan's law and push the negation all the way down inside the [
calls...
if [ ! -f file1 ] || [ ! -f file2 ] || [ ! -f file3 ]
then
# do stuff
fi
... or you must use then :; else
...
if [ -f file1 ] && [ -f file2 ] && [ -f file3 ]
then :
else
# do stuff
fi
if ! command
is not portably available and neither is [[
.
If you don't need total portability, don't write a shell script. You're actually more likely to find /usr/bin/perl
on a randomly selected Unix than you are bash
.
You could use entirely the test
functionality to achieve what you want. From the man page of test
:
! expression True if expression is false.
expression1 -a expression2
True if both expression1 and expression2 are true.
expression1 -o expression2
True if either expression1 or expression2 are true.
(expression) True if expression is true.
So your condition could look like:
if [ -f file1 -a -f file2 -a -f file3 ] ; then
# do stuff with the files
fi
For negating use escaped parentheses:
if [ ! \( -f file1 -a -f file2 -a -f file3 \) ] ; then
echo "Error: You done goofed."
exit 1
fi
# do stuff with the files