Expansão de parâmetros
A resposta óbvia é usar uma das formas especiais de expansão de parâmetros:
: ${STATE?"Need to set STATE"}
: ${DEST:?"Need to set DEST non-empty"}
Ou melhor (consulte a seção 'Posição das aspas duplas' abaixo):
: "${STATE?Need to set STATE}"
: "${DEST:?Need to set DEST non-empty}"
A primeira variante (usando just ?) requer que STATE seja definido, mas STATE = "" (uma sequência vazia) está OK - não exatamente o que você deseja, mas a notação alternativa e antiga.
A segunda variante (usando :?) requer que DEST seja definido e não esteja vazio.
Se você não fornecer nenhuma mensagem, o shell fornecerá uma mensagem padrão.
A ${var?}construção é portátil de volta à Versão 7 UNIX e ao Bourne Shell (1978 ou nos próximos anos). A ${var:?}construção é um pouco mais recente: acho que estava no System III UNIX por volta de 1981, mas pode ter sido no PWB UNIX antes disso. Está, portanto, no Korn Shell e nos shells POSIX, incluindo especificamente o Bash.
Geralmente é documentado na página de manual do shell em uma seção chamada Expansão de parâmetros . Por exemplo, o bashmanual diz:
${parameter:?word}
Exibir erro se nulo ou não definido. Se o parâmetro for nulo ou não definido, a expansão da palavra (ou uma mensagem nesse sentido se a palavra não estiver presente) será gravada no erro padrão e o shell, se não for interativo, será encerrado. Caso contrário, o valor do parâmetro é substituído.
O comando do cólon
Provavelmente devo acrescentar que o comando dois pontos simplesmente tem seus argumentos avaliados e depois é bem-sucedido. É a notação de comentário do shell original (antes de ' #' até o final da linha). Por um longo tempo, os scripts de shell Bourne tiveram dois pontos como o primeiro caractere. O Shell C leria um script e usaria o primeiro caractere para determinar se era para o Shell C (um #hash ' ') ou o shell Bourne ( :dois pontos ' '). Então o kernel entrou em ação e adicionou suporte aos comentários ' #!/path/to/program' e o shell Bourne recebeu ' #', e a convenção do cólon foi esquecida. Mas se você encontrar um script que comece com dois pontos, agora saberá o porquê.
Posição de aspas duplas
blong perguntou em um comentário :
Alguma opinião sobre essa discussão? https://github.com/koalaman/shellcheck/issues/380#issuecomment-145872749
A essência da discussão é:
… No entanto, quando eu shellcheck(com a versão 0.4.1), recebo esta mensagem:
In script.sh line 13:
: ${FOO:?"The environment variable 'FOO' must be set and non-empty"}
^-- SC2086: Double quote to prevent globbing and word splitting.
Algum conselho sobre o que devo fazer neste caso?
A resposta curta é "faça o que shellchecksugere":
: "${STATE?Need to set STATE}"
: "${DEST:?Need to set DEST non-empty}"
Para ilustrar o motivo, estude o seguinte. Observe que o :comando não ecoa seus argumentos (mas o shell avalia os argumentos). Queremos ver os argumentos, portanto, o código abaixo usa printf "%s\n"no lugar de :.
$ mkdir junk
$ cd junk
$ > abc
$ > def
$ > ghi
$
$ x="*"
$ printf "%s\n" ${x:?You must set x} # Careless; not recommended
abc
def
ghi
$ unset x
$ printf "%s\n" ${x:?You must set x} # Careless; not recommended
bash: x: You must set x
$ printf "%s\n" "${x:?You must set x}" # Careful: should be used
bash: x: You must set x
$ x="*"
$ printf "%s\n" "${x:?You must set x}" # Careful: should be used
*
$ printf "%s\n" ${x:?"You must set x"} # Not quite careful enough
abc
def
ghi
$ x=
$ printf "%s\n" ${x:?"You must set x"} # Not quite careful enough
bash: x: You must set x
$ unset x
$ printf "%s\n" ${x:?"You must set x"} # Not quite careful enough
bash: x: You must set x
$
Observe como o valor em $xé expandido para primeiro *e depois para uma lista de nomes de arquivos quando a expressão geral não está entre aspas duplas. Isto é o que shellcheckestá recomendando que deve ser corrigido. Não verifiquei que ela não se opõe ao formulário em que a expressão está entre aspas duplas, mas é uma suposição razoável de que estaria tudo bem.