Anteriormente, la respuesta se presentaba con lo que ahora es la primera sección como la última sección.
POSIX Shell incluye un !operador
Al hurgar en la especificación del shell por otros problemas, recientemente (septiembre de 2015) noté que el shell POSIX admite un !operador. Por ejemplo, aparece como una palabra reservada y puede aparecer al comienzo de una canalización , donde un comando simple es un caso especial de 'canalización'. Por lo tanto, también se puede usar en ifdeclaraciones whileo untilbucles, en shells compatibles con POSIX. En consecuencia, a pesar de mis reservas, probablemente esté más disponible de lo que me di cuenta en 2008. Una revisión rápida de POSIX 2004 y SUS / POSIX 1997 muestra que !estaba presente en ambas versiones.
Tenga en cuenta que el !operador debe aparecer al comienzo de la tubería y niega el código de estado de toda la tubería (es decir, el último comando). Aquí hay unos ejemplos.
$ ! 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
Respuesta portátil: funciona con conchas antiguas
En un script de Bourne (Korn, POSIX, Bash), uso:
if ...command and arguments...
then : it succeeded
else : it failed
fi
Esto es lo más portátil posible. El 'comando y argumentos' puede ser una canalización u otra secuencia compuesta de comandos.
Un notcomando
Los '!' El operador, ya sea integrado en su shell o proporcionado por el o / s, no está disponible universalmente. Sin embargo, no es terriblemente difícil de escribir: el código a continuación se remonta al menos a 1991 (aunque creo que escribí una versión anterior incluso hace más tiempo). Sin embargo, no suelo usar esto en mis scripts porque no está disponible de manera confiable.
/*
@(
@(
@(
@(
@(
@(
*/
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);
}
Esto devuelve "éxito", lo opuesto al fracaso, cuando no se ejecuta el comando. Podemos debatir si la opción "no hacer nada con éxito" era correcta; tal vez debería informar un error cuando no se le pide que haga nada. El código en " "stderr.h"" proporciona funciones sencillas de notificación de errores; lo uso en todas partes. Código fuente a pedido - vea mi página de perfil para contactarme.