Kann ich einen IF-Block in einer DOS-Batchdatei haben?


96

In einer DOS-Batchdatei können wir nur 1 Zeile haben, wenn Anweisungshauptteil? Ich glaube, ich habe irgendwo einen Ort gefunden, den ich ()für einen if-Block verwenden könnte, wie {}er in C-ähnlichen Programmiersprachen verwendet wird, aber er führt die Anweisungen nicht aus, wenn ich dies versuche. Auch keine Fehlermeldung. Dies ist mein Code:

if %GPMANAGER_FOUND%==true(echo GP Manager is up
goto Continue7
)
echo GP Manager is down
:Continue7

Seltsamerweise wird beim Ausführen der Batchdatei weder "GP Manager ist aktiv" noch "GP Manager ist nicht verfügbar" gedruckt.


Vielleicht könnte dies helfen: commandwindows.com/batchfiles-branching.htm
esaj

Ja, das hilft. DOS ist scheiße. Wenn ich mehrere Anweisungen verwenden möchte, wenn oder muss ich && zwischen Anweisungen verwenden? oder gibt es einen eleganteren Weg?
Hugh Darling

Antworten:


139

Sie können in der Tat einen Anweisungsblock erstellen, der nach einer Bedingung ausgeführt werden soll. Aber Sie haben die falsche Syntax. Die Klammern müssen genau wie gezeigt verwendet werden:

if <statement> (
    do something
) else (
    do something else
)

Ich glaube jedoch nicht, dass es eine eingebaute Syntax für else-ifAnweisungen gibt. Sie müssen leider verschachtelte ifAnweisungsblöcke erstellen, um dies zu handhaben.


Zweitens %GPMANAGER_FOUND% == truesieht dieser Test für mich sehr verdächtig aus. Ich weiß nicht, auf was die Umgebungsvariable eingestellt ist oder wie Sie sie einstellen, aber ich bezweifle sehr, dass der von Ihnen angezeigte Code das gewünschte Ergebnis liefert.


Der folgende Beispielcode funktioniert gut für mich:

@echo off

if ERRORLEVEL == 0 (
    echo GP Manager is up
    goto Continue7
)
echo GP Manager is down
:Continue7

Bitte beachten Sie einige spezifische Details zu meinem Beispielcode:

  • Das Leerzeichen zwischen dem Ende der bedingten Anweisung und der öffnenden Klammer.
  • Ich @echo offmöchte nicht alle Anweisungen sehen, die während der Ausführung auf der Konsole gedruckt werden, sondern nur die Ausgabe derjenigen, die speziell damit beginnen echo.
  • Ich verwende die eingebaute ERRORLEVELVariable nur als Test. Lesen Sie hier mehr

1
Besser verwenden, wenn% ERRORLEVEL% == 0 ist, da die andere Variante immer wahr ist, denn wenn ERRORLEVEL <N> wahr ist, wenn der Fehlerpegel gleich oder größer <N> ist, werden die "==" in diesem Fall ignoriert
jeb

@jeb: Ich denke, Sie haben den Punkt vielleicht verpasst. Verwenden ERRORLEVEList nicht die Antwort auf sein Problem. Ich habe lediglich ein Beispiel für die richtige Syntax veröffentlicht. Jede Form ist in diesem Fall genauso akzeptabel wie if 0 == 0jeder andere triviale Ausdruck. Stellen Sie jedoch sicher, dass Sie den Unterschied zwischen der Umgebungsvariablen %ERRORLEVEL%und der internen ERRORLEVELdes Befehlsprozessors verstehen . Raymond Chen erklärt es hier auf diesem Blog .
Cody Gray

Können Sie eine andere WENN haben?
Xagyg

1
Wenn Sie zu @ mythofechelons Kommentar hinzufügen, wird sogar eine scheinbar harmlose schließende Klammer in einer REM-Anweisung den Block beenden. zB Werfen REM This is a comment (or so I thought)in den IFBlock wird Sie durcheinander bringen.
Rkagerer

2
Sowohl @mythofechelon als auch @rkagerer weisen auf bestimmte Probleme einer allgemeinen Regel hin, nach der Zeichenfolgen in Anführungszeichen gesetzt werden müssen. Sie sollten niemals codieren, IF %somevar%==example_string2 es sollte immer Code sein, daher sollte der Operand in IF "value_of_somevar"=="example_string2"aufgelöst werden, um Sonderzeichen in beiden Zeichenfolgenoperanden zu vermeiden, die Syntaxfehler in der IFAnweisung verursachen. Die von Ihnen festgelegten Werte sollten immer so ausgeführt werden, set "somevar=value_of_somevar" dass Sie mit dieser Syntax Sonderzeichen in variablen Werten umgehen können. Hinweis das meine ich nicht set somevar="value_of_somevar"
Skip R

15

Logisch, Codys Antwort sollte funktionieren. Ich glaube jedoch nicht, dass die Eingabeaufforderung einen Codeblock logisch behandelt. Für mein Leben kann ich nicht erreichen, dass das mit mehr als einem einzelnen Befehl innerhalb des Blocks richtig funktioniert. In meinem Fall haben umfangreiche Tests ergeben, dass alle Befehle innerhalb des Blocks zwischengespeichert und gleichzeitig am Ende des Blocks ausgeführt werden. Dies führt natürlich nicht zu den erwarteten Ergebnissen. Hier ist ein stark vereinfachtes Beispiel:

if %ERRORLEVEL%==0 (
set var1=blue
set var2=cheese
set var3=%var1%_%var2%
)

Dies sollte var3 den folgenden Wert geben:

blue_cheese

sondern ergibt:

_

weil alle 3 Befehle beim Verlassen des Codeblocks zwischengespeichert und gleichzeitig ausgeführt werden.

Ich konnte dieses Problem lösen, indem ich den if-Block neu schrieb, um nur einen Befehl auszuführen - goto - und einige Beschriftungen hinzufügte. Es ist klobig und ich mag es nicht sehr, aber zumindest funktioniert es.

if %ERRORLEVEL%==0 goto :error0
goto :endif

:error0
set var1=blue
set var2=cheese
set var3=%var1%_%var2%

:endif

8
Die Verwendung einer verzögerten Erweiterung sollte funktionieren: Verwenden Sie:set var3=!var1!_!var2!
Dracorat

4

Versuchen Sie stattdessen, das kaufmännische Und & oder das doppelte kaufmännische Und && (abhängig von Fehlerstufe 0) als Befehlstrennzeichen zu verwenden.

Ich habe mit diesem Trick ein Skript-Snippet repariert. Zusammenfassend habe ich drei Batch-Dateien, von denen eine die beiden anderen aufruft, nachdem ich herausgefunden habe, welche Buchstaben den externen Sicherungslaufwerken zugewiesen wurden. Ich lasse die erste Datei auf dem primären externen Laufwerk, sodass die Aufrufe der Sicherungsroutine einwandfrei funktionierten, aber die Aufrufe des zweiten Laufwerks erforderten einen aktiven Laufwerkswechsel. Der folgende Code zeigt, wie ich das Problem behoben habe:

for %%b in (d e f g h i j k l m n o p q r s t u v w x y z) DO (
if exist "%%b:\Backup.cmd" %%b: & CALL "%%b:\Backup.cmd"
)

Warum um alles in der Welt wird das herabgestimmt? Genau das brauchte ich.
ggb667

1
@ GCB667 - Zur Verdeutlichung von @Louis "schrieb eine" Antwort ", die sich nicht auf das Problem bezieht, warum die IF-Anweisung für das Originalposter nicht funktioniert hat. Sie bezog sich auf eine Antwort von" vinniejohnson "(die auch das Problem mit den Originalplakaten übersehen hat). .
Überspringen Sie R

1

Ich bin auf diesen Artikel in den Ergebnissen gestoßen, die von einer Suche im Zusammenhang mit dem IF-Befehl in einer Batchdatei zurückgegeben wurden, und ich konnte der Gelegenheit nicht widerstehen, das Missverständnis zu korrigieren, dass IF-Blöcke auf einzelne Befehle beschränkt sind. Im Folgenden finden Sie einen Teil eines Windows NT-Produktionsbefehlsskripts, das täglich auf dem Computer ausgeführt wird, auf dem ich diese Antwort verfasse.

    if "%COPYTOOL%" equ "R" (
    WWLOGGER.exe "%APPDATA%\WizardWrx\%~n0.LOG" "Using RoboCopy to make a backup of %USERPROFILE%\My Documents\Outlook Files\*"
    %TOOLPATH% %SRCEPATH% %DESTPATH% /copyall %RCLOGSTR% /m /np /r:0 /tee
    C:\BIN\ExitCodeMapper.exe C:\BIN\ExitCodeMapper.INI[Robocopy] %TEMP%\%~n0.TMP %ERRORLEVEL%
) else (
    WWLOGGER.exe "%APPDATA%\WizardWrx\%~n0.LOG" "Using XCopy to make a backup of %USERPROFILE%\My Documents\Outlook Files\*"
    call %TOOLPATH%  "%USERPROFILE%\My Documents\Outlook Files\*" "%USERPROFILE%\My Documents\Outlook Files\_backups" /f /m /v /y
    C:\BIN\ExitCodeMapper.exe C:\BIN\ExitCodeMapper.INI[Xcopy] %TEMP%\%~n0.TMP %ERRORLEVEL%
)

Möglicherweise gelten Blöcke mit zwei oder mehr Zeilen ausschließlich für Windows NT-Befehlsskripte (CMD-Dateien), da bei einer Suche im Produktionsskriptverzeichnis einer Anwendung, die auf BAT-Dateien (Old School Batch) beschränkt ist, nur Ein-Befehlsblöcke angezeigt wurden . Da die Anwendung erweitert wurde (was bedeutet, dass ich nicht aktiv an der Unterstützung beteiligt bin), kann ich nicht sagen, ob dies daran liegt, dass ich nicht mehr als eine Zeile benötigte oder dass ich sie nicht zum Laufen bringen konnte.

Unabhängig davon, ob letzteres zutrifft, gibt es eine einfache Problemumgehung. Verschieben Sie die mehreren Zeilen entweder in eine separate Batchdatei oder in eine Batchdatei-Unterroutine. Ich weiß, dass Letzteres in beiden Arten von Skripten funktioniert.


0

Vielleicht etwas spät, aber ich hoffe, es geht schief:

@echo off 

if %ERRORLEVEL% == 0 (
msg * 1st line WORKS FINE rem You can relpace msg * with any othe operation...
goto Continue1
)
:Continue1
If exist "C:\Python31" (
msg * 2nd line WORKS FINE rem You can relpace msg * with any othe operation...
    goto Continue2
)
:Continue2
If exist "C:\Python31\Lib\site-packages\PyQt4" (  
msg * 3th line WORKS FINE rem You can relpace msg * with any othe operation...
    goto Continue3
)
:Continue3
msg * 4th line WORKS FINE rem You can relpace msg * with any othe operation...
    goto Continue4
)
:Continue4
msg * "Tutto a posto" rem You can relpace msg * with any othe operation...
pause
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.