Is test or [ or [[ more portable both between bash shells and between other shells?
Yes, there are differences. The most portable are test
or [ ]
. These are both part of the POSIX test
specification.
The if ... fi
construct is also defined by POSIX and should be completely portable.
The [[ ]]
is a ksh
feature that is also present in some versions of bash
(all modern ones), in zsh
and perhaps in others but is not present in sh
or dash
or the various other simpler shells.
So, to make your scripts portable, use [ ]
, test
or if ... fi
.
[
is synonym of the test
command and it is simultaneously a bash builtin and separate command. But [[
is a bash keyword and works in some versions only. So for reasons of portability you are better off using single []
or test
[ -w "/home/durrantm" ] && echo "writable"
Please note, that [] && cmd
is not the same as if .. fi
construction.
Sometimes its behaviour its pretty similar and you can use [] && cmd
instead of if .. fi
. But only sometimes. If you have more then one command to execute if condition or you need if .. else .. fi
be careful and whatch the logic.
A couple of examples:
[ -z "$VAR" ] && ls file || echo wiiii
Is not the same as
if [ -z $VAR ] ; then
ls file
else
echo wiii
fi
because if ls
will fail, echo
will be executed which will not happen with if
.
Another example:
[ -z "$VAR" ] && ls file && echo wiii
is not the same as
if [ -z "$VAR" ] ; then
ls file
echo $wiii
fi
though this construction will act the same
[ -z "$VAR" ] && { ls file ; echo wiii ; }
please note ;
after echo is important and must be there.
So resuming statement above we can say
[] && cmd
== if first command is successful then execute the next one
if .. fi
== if condition (which may be the test command as well) then execute command(s)
So for portability between [
and [[
use [
only.
if
is POSIX compatible. So if you have to choose between [
and if
choose looking at your task and expected behaviour.