Você sempre precisa de aspas em torno de variáveis em todos os contextos lista , ou seja, a variável pode ser expandida para vários valores, a menos que você queira os 3 efeitos colaterais de deixar uma variável sem aspas.
Os contextos list incluem argumentos para comandos simples como [ ou echo , o for i in <here> , atribuições a matrizes ... Existem outros contextos onde as variáveis também precisam ser citadas. O melhor é sempre citar variáveis, a menos que você tenha uma boa razão para não fazê-lo.
Pense na ausência de aspas (em contextos de lista) como o operador split + glob .
Como se echo $test fosse echo glob(split("$test")) .
O comportamento do shell é confuso para a maioria das pessoas porque na maioria das outras linguagens você coloca aspas em torno de strings fixas, como puts("foo") , e não em torno de variáveis (como puts(var) ) enquanto na shell é o contrário: tudo é string em shell, então colocar aspas em volta de tudo seria complicado, você echo test , você não precisa "echo" "test" . No shell, aspas são usadas para outra coisa: impedir algum significado especial de alguns caracteres e / ou afetar o comportamento de algumas expansões.
Em [ -n $test ] ou echo $test , o shell dividirá $test (em branco por padrão) e, em seguida, executará a geração de nome de arquivo (expanda todos os padrões * , '?' ... para a lista de arquivos correspondentes) e, em seguida, passe essa lista de argumentos para os comandos [ ou echo .
Novamente, pense nisso como "[" "-n" glob(split("$test")) "]" . Se $test estiver vazio ou contiver apenas espaços em branco (spc, tab, nl), então o operador split + glob retornará uma lista vazia, então [ -n $test ] será "[" "-n" "]" , que é um teste para verificar se "- n "é a string vazia ou não. Mas imagine o que teria acontecido se $test fosse "*" ou "= foo" ...
Em [ -n "$test" ] , [ é passado nos quatro argumentos "[" , "-n" , "" e "]" (sem as aspas), que é o que queremos.
Se é echo ou [ não faz diferença, é apenas que echo produz a mesma coisa se passou um argumento vazio ou nenhum argumento.
Veja também esta resposta a uma pergunta semelhante para obter mais detalhes sobre o comando [ e o [[...]] de construção.