Uma diferença entre [
e [[
é que [
não não faz avaliação aritmética, mas [[
faz:
$ [ "2 + 2" -eq 4 ] && echo yes
bash: [: 2 + 2: integer expression expected
$ [[ "2 + 2" -eq 4 ]] && echo yes
yes
A segunda sutileza é que, sempre que avaliação aritmética é executada no bash, as strings vazias são avaliadas como 0. Por exemplo:
$ x=""; echo $((0 + x))
0
$ [[ "" -eq 0 ]] && echo yes
yes
Documentação
De man bash
:
Shell variables are allowed as operands; parameter expansion is performed before the expression is evaluated. Within an expression, shell variables may also be referenced by name without using the parameter expansion syntax. A shell variable that is null or unset evaluates to 0 when referenced by name without using the parameter expansion syntax. The value of a variable is evaluated as an arithmetic expression when it is referenced, or when a variable which has been given the integer attribute using declare -i is assigned a value. A null value evaluates to 0. A shell variable need not have its integer attribute turned on to be used in an expression. [Emphasis added]
Além de: Problemas de segurança
Observe que a avaliação aritmética de bash é um possível problema de segurança. Por exemplo, considere:
x='a[$(rm -i *)]'
[[ x -eq 0 ]] && echo yes
Com a opção -i
, o acima é seguro, mas a lição geral é não usar a avaliação aritmética de bash com dados não higienizados.
Por outro lado, com [
, nenhuma avaliação aritmética é executada e, conseqüentemente, o comando nunca tenta excluir arquivos. Em vez disso, gera um erro com segurança:
$ x='a[$(rm -i *)]'
$ [ x -eq 0 ] && echo yes
bash: [: x: integer expression expected
Para saber mais sobre esse problema, consulte esta resposta .