Estoy buscando un proceso de negación simple pero multiplataforma que niegue el valor que devuelve un proceso. ¡Debe asignar 0 a algún valor! = 0 y cualquier valor! = 0 a 0, es decir, el siguiente comando debe devolver "sí, la ruta no existente no existe":
ls nonexistingpath | negate && echo "yes, nonexistingpath doesn't exist."
Los ! - el operador es excelente, pero desafortunadamente no es independiente del shell.
shell
cross-platform
negate
secr
fuente
fuente
Respuestas:
Anteriormente, la respuesta se presentaba con lo que ahora es la primera sección como la última sección.
POSIX Shell incluye un
!
operadorAl 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 enif
declaracioneswhile
ountil
bucles, 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.# Simple commands, pipes, and redirects work fine. $ ! some-command succeed; echo $? 1 $ ! some-command fail | some-other-command fail; echo $? 0 $ ! some-command < succeed.txt; echo $? 1 # Environment variables also work, but must come after the !. $ ! RESULT=fail some-command; echo $? 0 # A more complex example. $ 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
not
comandoLos '!' 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.
/* @(#)File: $RCSfile: not.c,v $ @(#)Version: $Revision: 4.2 $ @(#)Last changed: $Date: 2005/06/22 19:44:07 $ @(#)Purpose: Invert success/failure status of command @(#)Author: J Leffler @(#)Copyright: (C) JLSS 1991,1997,2005 */ #include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include <sys/wait.h> #include "stderr.h" #ifndef lint static const char sccs[] = "@(#)$Id: not.c,v 4.2 2005/06/22 19:44:07 jleffler Exp $"; #endif 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.fuente
!
operador. Esto funcionó para mí:! MY_ENV=value my_command
ldd foo.exe | ! grep badlib
pero puede hacerlo! ldd foo.exe | grep badlib
si desea que el estado de salida sea 0 si no se encuentra badlib en foo.exe. Semánticamente, desea invertir elgrep
estado, pero al invertir toda la tubería se obtiene el mismo resultado.ldd foo.exe | { ! grep badlib; }
(aunque es una molestia, especialmente el punto y coma; usted podría utilizar un sub-shell completa con(
y)
sin el punto y coma). OTOH, el objeto es invertir el estado de salida de la tubería, y ese es el estado de salida del último comando (excepto en Bash, a veces).!
comando tiene una interacción no deseada conset -e
, es decir, hace que el comando tenga éxito con un código de salida 0 o distinto de cero, en lugar de tener éxito solo con un código de salida distinto de cero. ¿Existe una forma concisa de hacerlo exitoso solo con un código de salida distinto de cero?En Bash, usa el! operador antes del comando. Por ejemplo:
! ls nonexistingpath && echo "yes, nonexistingpath doesn't exist"
fuente
Tu podrías intentar:
ls nonexistingpath || echo "yes, nonexistingpath doesn't exist."
o solo:
fuente
!
, no se puede usar congit bisect run
, o al menos no sé cómo.!
en ese caso.Si de alguna manera sucede que no tiene Bash como su shell (por ejemplo: scripts git o pruebas ejecutivas de títeres), puede ejecutar:
echo '! ls notexisting' | bash
-> código de retiro: 0
echo '! ls /' | bash
-> código de retiro: 1
fuente
! ls nonexistingpath && echo "yes, nonexistingpath doesn't exist."
o
ls nonexistingpath || echo "yes, nonexistingpath doesn't exist."
fuente
$?
será diferente. El primero podría irse$?=1
sinonexistingpath
realmente existe. El segundo siempre se va$?=0
. Si está usando esto en un Makefile y necesita confiar en el valor de retorno, debe tener cuidado.Nota: a veces verá
!(command || other command)
.Aquí
! ls nonexistingpath && echo "yes, nonexistingpath doesn't exist."
es suficiente.No se necesita un sub-caparazón.
Git 2.22 (Q2 2019) ilustra esa mejor forma con:
Confirma 74ec8cf , confirma 3fae7ad , confirma 0e67c32 , confirma 07353d9 , confirma 3bc2702 , confirma 8c3b9f7 , confirma 80a539a , confirma c5c39f4 (13 de marzo de 2019) por SZEDER Gábor (
szeder
) .Consulte la confirmación 99e37c2 , la confirmación 9f82b2a , la confirmación 900721e (13 de marzo de 2019) de Johannes Schindelin (
dscho
) .(Combinado con Junio C Hamano -
gitster
- en el compromiso 579b75a , 25 de abril de 2019)fuente
Solución sin!, Sin subshell, sin if, y debería funcionar al menos en bash:
ls nonexistingpath; test $? -eq 2 && echo "yes, nonexistingpath doesn't exist." # alternatively without error message and handling of any error code > 0 ls nonexistingpath 2>/dev/null; test $? -gt 0 && echo "yes, nonexistingpath doesn't exist."
fuente