
Ich erstelle eine SH-Datei, um mehrere Befehle im Hintergrund auszuführen.
In einer beliebigen Zeile dieser Datei befindet sich ein Befehl zum Aktualisieren einer ZIP-Datei wie:
zip -d archive.zip file.txt
Diese Datei.txt ist möglicherweise nicht immer Teil der Archiv.zip. Wenn dies nicht der Fall ist, bricht das Shell-Skript in dieser Zeile mit folgendem ab:
zip warning: name not matched
Ich möchte, dass es mit den folgenden Zeilen fortfährt und die Nichtexistenz dieser Datei ignoriert. Wie kann ich das erreichen?
Antwort1
Normalerweise wird die Ausführung eines Shell-Skripts auch dann nicht gestoppt, wenn eine Zeile einen Fehler erzeugt. Das Skript fährt einfach mit der nächsten Zeile fort.
Die bemerkenswerte Ausnahme ist, wenn Sie das Flag gesetzt haben, damit die Shell beendet wird, wenn ein Unterbefehl fehlschlägt. Dies wird manchmal erreicht, indem man am Anfang eines Skripts „set -e“ hinzufügt. Wenn Sie so etwas in Ihrem Skript haben, wird es bei jedem Befehl im Skript abgebrochen, der einen Fehler zurückgibt. Ihre Optionen in diesem Fall sind:
Entfernen Sie diese Option. Dies könnte Auswirkungen auf den Rest Ihres Skripts haben, also tun Sie dies nicht aus einer Laune heraus.
Deaktivieren Sie die Option für den Abschnitt des Skripts, in dem Sie sich befinden, und aktivieren Sie sie dann wieder, um fortzufahren:
set +e zip -d archive.zip file.txt set -e
Geben Sie einen Ausweg für die fehlgeschlagene Zeile an, damit die Shell den Befehl als erfolgreich ansieht, auch wenn etwas fehlgeschlagen ist. Dies kann auf viele Arten erfolgen, aber eine einfache Möglichkeit ist die Verwendung des OR-Operators:
zip -d archive.zip file.txt || true
Dadurch wird der Befehl zip ausgeführt. Wenn dies jedoch fehlschlägt, wird der Befehl true ausgeführt und die übergeordnete Shell erhält den Rückgabecode davon (was natürlich ein Erfolg ist). Sie werden dies möglicherweise manchmal geschrieben sehen,
||:
was etwas schneller und kniffliger ist, aber keine Zauberei;:
es handelt sich einfach um einen in der Shell integrierten No-Op-Befehl, der auch einen Erfolgsfehlercode zurückgibt, obwohl er nichts tut.Eine andere Möglichkeit besteht darin, den Befehl in einer Sub-Shell auszuführen, indem man ihn umschließt,
()
sodass der Befehl darin zwar fehlschlagen kann, die Sub-Shell aber ihre Arbeit erledigt hat, sodass das übergeordnete Skript mitset -e
dem Set nicht beendet wird. Dies ist für einen einzelnen Befehl nicht optimal, kann aber nützlich sein, wenn Sie eine ganze Reihe von Dingen ausführen möchten.
Wenn Sie andererseits nur die von Zip generierte Fehlermeldung unterdrücken möchten, können Sie den Standardfehlerstrom mit ( 2> /dev/null
) nach /dev/null umleiten, um die generierten Meldungen zu unterdrücken (oder ihn mit schließen 2>&-
).