Bestimmen Sie, ob der Befehl in einer Stapeldatei erkannt wird

43

Ich schreibe ein Fledermaus-Skript, in dem ich ein Programm aufrufe (z. B. javac). Der Einfachheit halber möchte ich überprüfen, ob der Befehl vorhanden ist, bevor ich ihn ausführe. dh wenn der Befehl in PATH existiert.

Zum Beispiel,

if (my_command.exe is a recognized command) then (
  my_command.exe my_args
) else (
  REM Output was probably "'my_command.exe' is not recognized as an internal or external command, operable program or batch file."
  REM Do not run my_command.exe
)

Was ist der beste Weg, um dies in Windows zu tun?

user46097
quelle
Woran erkennen Sie Ihren Befehl?
Rook
In MS-DOS (echtes DOS) war dies ziemlich einfach; Sie haben gerade das Vorhandensein einer exe-Datei in c: \ dos überprüft. aber auch dann bleibt die frage.
Rook
Entschuldigung für die Verwirrung. Ich meinte im Wesentlichen eine Eingabeaufforderung in Windows. Wenn ich "lkajsflksajdfj" eingebe, möchte ich erkennen, dass es sich nicht um einen Befehl handelt. Wenn ich "notepad.exe" eingebe, ist es OK.
user46097

Antworten:

54
WHERE mycommand
IF %ERRORLEVEL% NEQ 0 ECHO mycommand wasn't found 
Josh Santangelo
quelle
10
Wenn jemand die Ausgabe im cmd-Fenster nicht will, füge sie einfach >nul 2>nulhinter dem hinzu mycommand.
Sebastian
Beachten Sie, dass es mehr Ausgabekanäle als 1 und 2 gibt, da 1 für Ausgabepuffer und 2 für Fehlerpuffer steht. Dies hängt davon ab, wie die Anwendung entwickelt wurde. Es sollte für gängige Apps funktionieren, die mit Windows geliefert werden, aber ein bestimmtes CLI-Programm könnte wirft immer noch Text, wenn die Kanäle 1 und 2 umgeleitet werden.
ElektroStudios
15

Der folgende Code sollte immer sauber und ohne Müllausgabe ausgeführt werden.

javac -version >nul 2>&1 && (
    echo found javac
) || (
    echo fail
)

Ausgabe:

found javac

Der gleiche Code wie bei einem Einzeiler:

javaz -version >nul 2>&1 && ( echo found javac ) || ( echo fail )

Ausgabe:

fail

Beachten Sie, dass die Reihenfolge von &&und ||wichtig zu sein scheint. Außerdem muss der Befehl, auf dessen Existenz Sie testen, mit einer Fehlerebene <= 0 zurückgegeben werden, damit dies funktioniert. Hoffentlich hat der Befehl /? oder --help Argumente oder, wie bei Java, ein Versionsinformationsbefehl.

ngreen
quelle
Diese Lösung ist perfekt!
Robe007
7

Der einfachste Weg ist, einfach den Befehl auszuführen, aber das hat natürlich andere Probleme, da Sie vielleicht nicht möchten, dass ein zufälliger Prozess gestartet wird.

for %%x in (my_command.exe) do if not [%%~$PATH:x]==[] set MyCommandFound=1

ist eine Alternative, die nach dem Programm in den Pfaden sucht, die von der %PATH%Umgebungsvariablen aufgelistet werden . Es ist im Wesentlichen eine reine Batch-Version von which(1). Es kann besser gemacht werden, aber im Wesentlichen ist es das.

Joey
quelle
1
Das ist perfekt, macht genau das, wonach man gefragt hat!
Pez Cuckow
3

Für meine Situation. Der absolut einfachste Weg ist die Verwendung von || oder && Operator.

my_command.exe -version 2>NUL && echo "my_command exists"

oder

my_command.exe -version 2>NUL || echo "my_command doesn't exist"
user46097
quelle
Warum leiten Sie stdout nicht auch um?
Joey
3

Einige Verfeinerungen zur Version unten. Testen Sie, ob der Befehl vorhanden ist, und unterdrücken Sie nicht benötigte Ausgaben.

WHERE scp >nul 2>nul
IF %ERRORLEVEL% EQU 0 ECHO scp found
yuliskov
quelle
wo <my_exe> NUL 2> & 1 || echo my.exe existiert nicht && goto: EOF funktioniert gut in Skripten
Robert
Hinweis: Dies funktioniert nicht, wenn der zu testende Dateiname Pfadinformationen enthält. ZB WHERE \Windows\System32\cmd.exe=>INFO: Could not find files for the given pattern(s).
Jonathan Gilbert
1

Wenn es in Ordnung ist, zusätzliche Tools zu installieren, finden Sie wherein den Resource Kits einen Befehl. siehe Windows-Äquivalent von whereis? .

Andernfalls ist es für Windows-Versionen, die nicht zu alt sind, in reiner Form möglich cmd, wie in DOS Executable Lookup (außer PATH) erwähnt .

Gilles 'SO - hör auf böse zu sein'
quelle
Danke für die Antwort! Unglücklicherweise ist eine der Anforderungen, dass es auf einer Vanille-Box (einschließlich XP-Maschinen) ausgeführt werden muss - also ist whereis keine Option.
user46097
2
Der zweite Link, den Gilles gab, hat eine raffinierte Lösung, die FOR und keine zusätzlichen Tools verwendet.
Paradroid
1

Ich weiß, dass dies nicht ganz das ist, wonach Sie suchen, aber mit einer geringfügigen Änderung der Logik sollte es das erreichen, was Sie benötigen.

Jeder ausgeführte Befehl hat einen Rückgabecode (auch bekannt als Errorlevel). Wenn der Rückgabecode 0 (Null) ist, wurde der Befehl erfolgreich ausgeführt. Wenn der Rückgabecode größer als 0 ist, ist ein Fehler aufgetreten.

Sehen Sie hier für weitere Details.

So etwas wie -

my_command
if (%ERRORLEVEL% > 0) then (
  REM Output was probably "'my_command.exe' is not recognized as an internal or external command, operable program or batch file.  OR SOMETHING WENT WRONG WITH IT."
  REM Do not run my_command.exe
)
bryan
quelle
Das ist schlau, ich mag es.
Shinrai
Ja, aber es ist hässlich, wenn der Befehl nicht gefunden wird, wird ein 2-Zeilen-Fehler ausgegeben. So könnte möglicherweise eine sauberere Lösung gefunden werden.
Djangofan
0

Während all diese Möglichkeiten funktionieren könnten, warum nicht die eingebauten Möglichkeiten?

If exists my_command do echo "my_command exists"

Führen Sie "if /?" in der Befehlszeile für Details

uSlackr
quelle
5
Dies prüft nur, ob eine Datei / ein Verzeichnis mit diesem Namen im aktuellen Verzeichnis vorhanden ist. Es gibt kaum einen Hinweis darauf, ob ein ausführbarer Befehl mit diesem Namen vorhanden ist, um zu bestimmen, dass Sie den suchen müssten PATH.
Joey