De Manual de Referência Bash :
${parameter:?word}
E se parameter é nulo ou não definido, a expansão de word (ou uma mensagem para esse efeito se word não está presente) é gravado no erro padrão e o shell, se não for interativo, sai. Caso contrário, o valor de parameter é substituído.
Pode não ser óbvio, mas "erro padrão" significa o erro padrão da casca . Quando você faz echo … 2> testfile você redireciona o erro padrão de echo. Ambos normalmente acabam no seu terminal, mas não são iguais.
Para fazê-lo funcionar como você quer criar um subshell e redirecionar Está erro padrão:
(echo ${var:?"This var is not set"}) 2> testfile
Isso também funcionará:
{ echo ${var:?"This var is not set"}; } 2> testfile
Observe o comando real ( echo ) herdará o erro padrão já redirecionado do subshell, portanto, esse redirecionamento afeta ambos. Quase nunca importa quando o comando é echo mas com um comando que retorna uma mensagem de erro. Comparar:
unset var
(dd ${var:?"This var is not set"}) 2> testfile
cat testfile
var=foo
(dd ${var:?"This var is not set"}) 2> testfile
cat testfile