
vejo que posso fazer
$ [ -w /home/durrantm ] && echo "writable"
writable
ou
$ test -w /home/durrantm && echo "writable"
writable
ou
$ [[ -w /home/durrantm ]] && echo "writable"
writable
Gosto de usar a terceira sintaxe. Eles são equivalentes em todos os aspectos e para todos os casos negativos e extremos? Há alguma diferença na portabilidade, por exemplo, entre o bash no Ubuntu e no OS X ou versões mais antigas/mais recentes do bash, por exemplo, antes/depois do 4.0 e ambos expandem as expressões da mesma maneira?
Responder1
Sim, existem diferenças. Os mais portáteis são test
ou [ ]
. Ambos fazem parte dotest
Especificação POSIX.
A if ... fi
construção também édefinido por POSIXe deve ser totalmente portátil.
O [[ ]]
é um ksh
recurso que também está presente em algumas versões de bash
(todos os modernos), em zsh
e talvez em outros, mas não está presente em sh
ou dash
em vários outros shells mais simples.
Portanto, para tornar seus scripts portáveis, use [ ]
, test
ou if ... fi
.
Responder2
[
é sinônimo de test
comando e é simultaneamente umbash embutidoe comando separado. Mas [[
é umpalavra-chave bashe funciona apenas em algumas versões. Portanto, por razões de portabilidade, é melhor usar um único []
outest
[ -w "/home/durrantm" ] && echo "writable"
Responder3
Observe que isso [] && cmd
não é o mesmo que if .. fi
construção.
Às vezes, seu comportamento é bastante semelhante e você pode usar [] && cmd
em vez de if .. fi
. Mas só às vezes. Se você tiver mais de um comando para executar a condição ou precisar if .. else .. fi
ter cuidado e verificar a lógica.
Alguns exemplos:
[ -z "$VAR" ] && ls file || echo wiiii
Não é o mesmo que
if [ -z $VAR ] ; then
ls file
else
echo wiii
fi
porque se ls
falhar, echo
será executado o que não acontecerá com if
.
Outro exemplo:
[ -z "$VAR" ] && ls file && echo wiii
não é o mesmo que
if [ -z "$VAR" ] ; then
ls file
echo $wiii
fi
embora esta construção irá agir da mesma forma
[ -z "$VAR" ] && { ls file ; echo wiii ; }
observe que ;
depois do eco é importante e deve estar lá.
Então, retomando a afirmação acima, podemos dizer
[] && cmd
== se o primeiro comando for bem-sucedido, execute o próximo
if .. fi
== if condição (que também pode ser o comando de teste) então execute o(s) comando(s)
Portanto, para portabilidade entre [
e apenas [[
para uso [
.
if
é compatível com POSIX. Portanto, se você tiver que escolher entre [
e if
escolher, observe sua tarefa e o comportamento esperado.
Responder4
Para portabilidade, use test
/ [
. Mas se você não precisa de portabilidade, para sua sanidade e de outras pessoas que leem seu script, use [[
. :)
Veja também What is the difference between test, [ and [[ ?
noBashFAQ.