O teste ou [ ou [[ é mais portátil entre shells bash e entre outros shells?

O teste ou [ ou [[ é mais portátil entre shells bash e entre outros shells?

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 testou [ ]. Ambos fazem parte dotestEspecificação POSIX.

A if ... ficonstrução também édefinido por POSIXe deve ser totalmente portátil.

O [[ ]]é um kshrecurso que também está presente em algumas versões de bash(todos os modernos), em zshe talvez em outros, mas não está presente em shou dashem vários outros shells mais simples.

Portanto, para tornar seus scripts portáveis, use [ ], testou if ... fi.

Responder2

[é sinônimo de testcomando 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 [] && cmdnão é o mesmo que if .. ficonstrução.

Às vezes, seu comportamento é bastante semelhante e você pode usar [] && cmdem vez de if .. fi. Mas só às vezes. Se você tiver mais de um comando para executar a condição ou precisar if .. else .. fiter 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 lsfalhar, echoserá 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 ifescolher, 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.

informação relacionada