3131 Stimmen

Wie kann ich von einem Bash-Skript aus prüfen, ob ein Programm existiert?

Wie kann ich überprüfen, ob ein Programm existiert, und zwar so, dass es entweder einen Fehler zurückgibt und beendet wird oder mit dem Skript fortfährt?

Es sollte eigentlich ganz einfach sein, aber es hat mich nicht weitergebracht.

2 Stimmen

Was ist ein "Programm"? Beinhaltet es Funktionen und Aliasnamen? which gibt für diese den Wert true zurück. type ohne Argumente gibt zusätzlich true für reservierte Wörter und Shell-Builtins zurück. Wenn "Programm" bedeutet "auswählbar in $PATH ", dann siehe diese Antwort .

0 Stimmen

@TomHale Es hängt davon ab, welche Implementierung von which die Sie verwenden; diese wird nicht von der Bash, sondern z.B. von Debian's debianutils bereitgestellt.

49voto

Romário Punkte 1465

Ergänzend zu den Antworten von @lhunath und @GregV, hier der Code für alle, die diese Prüfung einfach in eine if Erklärung:

exists()
{
  command -v "$1" >/dev/null 2>&1
}

So verwenden Sie es:

if exists bash; then
  echo 'Bash exists!'
else
  echo 'Your system does not have Bash'
fi

15 Stimmen

Die Bereitschaft, zu lernen und sich zu verbessern, muss belohnt werden. +1 Das ist klar und einfach. Das Einzige, was ich hinzufügen kann, ist, dass command gelingt auch bei Aliasen, was vielleicht etwas kontraintuitiv ist. Die Prüfung auf Existenz in einer interaktiven Shell wird andere Ergebnisse liefern, als wenn man sie in ein Skript verschiebt.

2 Stimmen

Ich habe gerade getestet und mit shopt -u expand_aliases ignoriert/versteckt Aliasnamen (wie die alias ls='ls -F' in einer anderen Antwort erwähnt) und shopt -s expand_aliases löst sie auf über command -v . Vielleicht sollte sie also vor der Prüfung gesetzt und danach wieder aufgehoben werden, obwohl sie den Rückgabewert der Funktion beeinflussen könnte, wenn Sie die Ausgabe des Befehlsaufrufs nicht explizit erfassen und zurückgeben.

0 Stimmen

Warum funktioniert das nicht bei if exists conda; then auch wenn anaconda installiert ist und zurückkehrt: usage: conda [-h] [-V] command... wenn man eintritt conda im Terminal? (Hinweis: Ich habe überprüft, dass Ihre Antwort mit if exists bash; then auf einem Ubuntu 20 Betriebssystem).

33voto

Versuchen Sie es mit:

test -x filename

o

[ -x filename ]

Aus der Bash-Manpage unter Bedingte Ausdrücke :

 -x file
          True if file exists and is executable.

37 Stimmen

Das bedeutet, dass Sie bereits den vollständigen Pfad zur Anwendung kennen müssen.

14 Stimmen

Der OP hat nicht angegeben, ob er nach einer bestimmten Instanz oder nach jeder ausführbaren Instanz suchen wollte... Ich habe so geantwortet, wie ich es gelesen habe.

20voto

dcharles Punkte 4682

Zur Verwendung hash , wie @lhunath vorschlägt in einem Bash-Skript:

hash foo &> /dev/null
if [ $? -eq 1 ]; then
    echo >&2 "foo not found."
fi

Dieses Skript läuft hash und prüft dann, ob der Exit-Code des letzten Befehls, der Wert, der in $? ist gleich 1 . Wenn hash findet nicht foo wird der Exit-Code sein 1 . Wenn foo vorhanden ist, lautet der Exit-Code 0 .

&> /dev/null leitet um. Standardfehler y Standardausgabe von hash so dass sie nicht auf dem Bildschirm erscheint und echo >&2 schreibt die Nachricht in den Standardfehler.

11 Stimmen

Warum nicht einfach if hash foo &> /dev/null; then ... ?

2 Stimmen

もし set -e eingestellt war, wurde die if... Teil wurde nie ausgeführt.

17voto

AnthonyC Punkte 1660

Befehl -v funktioniert gut, wenn die Option POSIX_BUILTINS für die <command> zu testen, aber es kann fehlschlagen, wenn nicht. (Bei mir hat es jahrelang funktioniert, aber vor kurzem bin ich auf einen Fall gestoßen, in dem es nicht funktioniert hat).

Ich halte das Folgende für ausfallsicherer:

test -x "$(which <command>)"

Denn es testet auf drei Dinge: Pfad, Existenz und Ausführungserlaubnis.

0 Stimmen

Funktioniert nicht. test -x $(which ls) gibt 0 zurück, ebenso wie die test -x $(which sudo) auch wenn ls installiert und lauffähig ist und sudo ist nicht einmal in dem Docker-Container installiert, in dem ich arbeite.

2 Stimmen

@algal Ich glaube, Sie müssen Anführungszeichen verwenden, also test -x "$(which <command>)"

0 Stimmen

@algal Vielleicht ls ein Alias ist? Ich glaube nicht, dass es funktionieren würde, wenn der Befehl Parameter hat.

15voto

0xF Punkte 2553

Wenn Sie prüfen, ob ein Programm vorhanden ist, werden Sie es wahrscheinlich sowieso später ausführen. Warum versuchen Sie nicht, es überhaupt zu starten?

if foo --version >/dev/null 2>&1; then
    echo Found
else
    echo Not found
fi

Es ist eine vertrauenswürdigere Überprüfung, dass das Programm läuft, als wenn man nur die PATH-Verzeichnisse und Dateiberechtigungen überprüft.

Außerdem können Sie einige nützliche Ergebnisse von Ihrem Programm erhalten, z. B. seine Version.

Der Nachteil ist natürlich, dass manche Programme schwer zu starten sind und manche keine --version Option, um das Programm sofort (und erfolgreich) zu beenden.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X