Anteriormente, a resposta era apresentada com o que agora é a primeira seção como a última seção.
POSIX Shell inclui um !
operador
Pesquisando na especificação do shell para outros problemas, recentemente (setembro de 2015) notei que o shell POSIX oferece suporte a um !
operador. Por exemplo, ele é listado como uma palavra reservada e pode aparecer no início de um pipeline - onde um comando simples é um caso especial de 'pipeline'. Ele pode, portanto, ser usado em if
instruções e / while
ou until
loops também - em shells compatíveis com POSIX. Consequentemente, apesar de minhas reservas, provavelmente está mais disponível do que eu percebi em 2008. Uma verificação rápida do POSIX 2004 e do SUS / POSIX 1997 mostra que !
estava presente em ambas as versões.
Observe que o !
operador deve aparecer no início do pipeline e nega o código de status de todo o pipeline (ou seja, o último comando). Aqui estão alguns exemplos.
$ ! some-command succeed; echo $?
1
$ ! some-command fail | some-other-command fail; echo $?
0
$ ! some-command < succeed.txt; echo $?
1
$ ! RESULT=fail some-command; echo $?
0
$ if ! some-command < input.txt | grep Success > /dev/null; then echo 'Failure!'; recover-command; mv input.txt input-failed.txt; fi
Failure!
$ ls *.txt
input-failed.txt
Resposta portátil - funciona com conchas antigas
Em um script Bourne (Korn, POSIX, Bash), eu uso:
if ...command and arguments...
then : it succeeded
else : it failed
fi
Isso é tão portátil quanto possível. O 'comando e argumentos' pode ser um pipeline ou outra sequência composta de comandos.
Um not
comando
O '!' operador, seja embutido em seu shell ou fornecido pelo o / s, não está universalmente disponível. No entanto, não é terrivelmente difícil de escrever - o código a seguir data de pelo menos 1991 (embora eu ache que escrevi uma versão anterior ainda mais atrás). Eu não costumo usar isso em meus scripts, porque não está disponível de forma confiável.
/*
@(
@(
@(
@(
@(
@(
*/
static const char sccs[] = "@(#)$Id: not.c,v 4.2 2005/06/22 19:44:07 jleffler Exp $";
int main(int argc, char **argv)
{
int pid;
int corpse;
int status;
err_setarg0(argv[0]);
if (argc <= 1)
{
/* Nothing to execute. Nothing executed successfully. */
/* Inverted exit condition is non-zero */
exit(1);
}
if ((pid = fork()) < 0)
err_syserr("failed to fork\n");
if (pid == 0)
{
/* Child: execute command using PATH etc. */
execvp(argv[1], &argv[1]);
err_syserr("failed to execute command %s\n", argv[1]);
/* NOTREACHED */
}
/* Parent */
while ((corpse = wait(&status)) > 0)
{
if (corpse == pid)
{
/* Status contains exit status of child. */
/* If exit status of child is zero, it succeeded, and we should
exit with a non-zero status */
/* If exit status of child is non-zero, if failed and we should
exit with zero status */
exit(status == 0);
/* NOTREACHED */
}
}
/* Failed to receive notification of child's death -- assume it failed */
return (0);
}
Isso retorna 'sucesso', o oposto de falha, quando falha ao executar o comando. Podemos debater se a opção 'não fazer nada com sucesso' estava correta; talvez ele deva relatar um erro quando não for solicitado a fazer nada. O código em ' "stderr.h"
' fornece recursos de relatório de erros simples - eu o uso em qualquer lugar. Código-fonte a pedido - consulte minha página de perfil para entrar em contato comigo.