Ich bin auf der Suche nach einem einfachen, aber plattformübergreifende negate -Prozess , dass der Wert ein Prozess kehrt negiert. Es sollte 0 einem bestimmten Wert zuordnen! = 0 und einen beliebigen Wert! = 0 bis 0, dh der folgende Befehl sollte "yes, noneististingpath existiert nicht" zurückgeben:
ls nonexistingpath | negate && echo "yes, nonexistingpath doesn't exist."
Das ! - Operator ist großartig, aber leider nicht Shell-unabhängig.
Antworten:
Zuvor wurde die Antwort mit dem jetzt ersten Abschnitt als letztem Abschnitt präsentiert.
Die POSIX-Shell enthält einen
!
OperatorBeim Stöbern in der Shell-Spezifikation für andere Probleme habe ich kürzlich (September 2015) festgestellt, dass die POSIX-Shell einen
!
Operator unterstützt . Beispielsweise wird es als reserviertes Wort aufgeführt und kann am Anfang einer Pipeline angezeigt werden - wobei ein einfacher Befehl ein Sonderfall von 'Pipeline' ist. Es kann daher auch inif
Anweisungen und /while
oderuntil
Schleifen verwendet werden - in POSIX-kompatiblen Shells. Folglich ist es trotz meiner Vorbehalte wahrscheinlich weiter verbreitet als ich 2008 festgestellt habe. Eine kurze Überprüfung von POSIX 2004 und SUS / POSIX 1997 zeigt, dass!
es in beiden Versionen vorhanden war.Beachten Sie, dass der
!
Operator am Anfang der Pipeline erscheinen muss und den Statuscode der gesamten Pipeline negiert (dh den letzten Befehl). Hier sind einige Beispiele.# 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
Tragbare Antwort - funktioniert mit antiken Muscheln
In einem Bourne-Skript (Korn, POSIX, Bash) verwende ich:
if ...command and arguments... then : it succeeded else : it failed fi
Dies ist so portabel wie es nur geht. Der 'Befehl und die Argumente' können eine Pipeline oder eine andere zusammengesetzte Folge von Befehlen sein.
Ein
not
BefehlDas '!' Der in Ihre Shell integrierte oder von den Betriebssystemen bereitgestellte Operator ist nicht allgemein verfügbar. Es ist jedoch nicht besonders schwer zu schreiben - der folgende Code stammt mindestens aus dem Jahr 1991 (obwohl ich glaube, dass ich vor einiger Zeit eine frühere Version geschrieben habe). Ich verwende dies jedoch nicht in meinen Skripten, da es nicht zuverlässig verfügbar ist.
/* @(#)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); }
Dies gibt 'Erfolg' zurück, das Gegenteil von Fehler, wenn der Befehl nicht ausgeführt werden kann. Wir können darüber diskutieren, ob die Option "Nichts erfolgreich machen" richtig war. Vielleicht sollte es einen Fehler melden, wenn es nicht aufgefordert wird, etwas zu tun. Der Code in '
"stderr.h"
' bietet einfache Funktionen zur Fehlerberichterstattung - ich verwende ihn überall. Quellcode auf Anfrage - siehe meine Profilseite, um mich zu kontaktieren.quelle
!
Operator folgen . Das hat bei mir funktioniert:! MY_ENV=value my_command
ldd foo.exe | ! grep badlib
aber Sie können es tun,! ldd foo.exe | grep badlib
wenn der Exit-Status 0 sein soll, wenn badlib nicht in foo.exe gefunden wird. Semantisch möchten Sie dengrep
Status invertieren, aber das Invertieren der gesamten Pipe führt zum gleichen Ergebnis.ldd foo.exe | { ! grep badlib; }
(obwohl es ein Ärgernis, vor allem des Semikolon, man kann eine vollständige Unterschale mit nutzen könnte(
und)
ohne das Semikolon). OTOH, das Ziel ist es, den Exit-Status der Pipeline zu invertieren, und das ist der Exit-Status des letzten Befehls (außer manchmal in Bash).!
Befehl eine unerwünschte Interaktion mitset -e
, dh er bewirkt, dass der Befehl mit einem Exit-Code von 0 oder ungleich Null erfolgreich ist, anstatt nur mit einem Exit-Code ungleich Null erfolgreich zu sein. Gibt es eine präzise Möglichkeit, dies nur mit einem Exit-Code ungleich Null zum Erfolg zu führen ?Verwenden Sie in Bash die! Operator vor dem Befehl. Zum Beispiel:
! ls nonexistingpath && echo "yes, nonexistingpath doesn't exist"
quelle
Du könntest es versuchen:
ls nonexistingpath || echo "yes, nonexistingpath doesn't exist."
oder nur:
quelle
!
Kann leider nicht verwendet werdengit bisect run
, oder zumindest weiß ich nicht wie.!
in diesem Fall nicht.Wenn es irgendwie passiert, dass Sie Bash nicht als Shell haben (z. B. Git-Skripte oder Puppet Exec-Tests), können Sie Folgendes ausführen:
echo '! ls notexisting' | bash
-> Retcode: 0
echo '! ls /' | bash
-> Retcode: 1
quelle
! ls nonexistingpath && echo "yes, nonexistingpath doesn't exist."
oder
ls nonexistingpath || echo "yes, nonexistingpath doesn't exist."
quelle
$?
ist unterschiedlich. Der erste könnte gehen,$?=1
wenn dasnonexistingpath
tatsächlich existiert. Der zweite geht immer$?=0
. Wenn Sie dies in einem Makefile verwenden und sich auf den Rückgabewert verlassen müssen, müssen Sie vorsichtig sein.Hinweis: Manchmal werden Sie sehen
!(command || other command)
.Hier
! ls nonexistingpath && echo "yes, nonexistingpath doesn't exist."
ist genug.Keine Unterschale erforderlich.
Git 2.22 (Q2 2019) veranschaulicht diese bessere Form mit:
Commit 74ec8cf , Commit 3fae7ad , Commit 0e67c32 , Commit 07353d9 , Commit 3bc2702 , Commit 8c3b9f7 , Commit 80a539a , Commit c5c39f4 (13. März 2019) von SZEDER Gábor (
szeder
) .Siehe Commit 99e37c2 , Commit 9f82b2a , Commit 900721e (13. März 2019) von Johannes Schindelin (
dscho
) .(Zusammengeführt von Junio C Hamano -
gitster
- in Commit 579b75a , 25. April 2019)quelle
Lösung ohne !, Ohne Unterschale, ohne Wenn und sollte zumindest in Bash funktionieren:
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."
quelle