Posso avere un blocco IF nel file batch DOS?


97

In un file batch DOS possiamo avere solo 1 riga if corpo dell'istruzione? Penso di aver trovato un posto che potrei usare ()per un blocco if proprio come quello {}usato nei linguaggi di programmazione C-like, ma non sta eseguendo le istruzioni quando provo questo. Nessun messaggio di errore neanche. Questo il mio codice:

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

Stranamente né "GP Manager è attivo" né "GP Manager è inattivo" vengono stampati quando eseguo il file batch.


Forse questo potrebbe aiutare: commandwindows.com/batchfiles-branching.htm
esaj

Sì, questo aiuta. Il DOS fa schifo. Se voglio usare più istruzioni in if oppure devo usare && tra le istruzioni? o c'è un modo più elegante?
Hugh Darling

Risposte:


141

Puoi effettivamente inserire un blocco di istruzioni da eseguire dopo un condizionale. Ma hai la sintassi sbagliata. Le parentesi devono essere utilizzate esattamente come mostrato:

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

Tuttavia, non credo che esista una sintassi incorporata per le else-ifistruzioni. Sfortunatamente dovrai creare blocchi annidati di ifistruzioni per gestirlo.


In secondo luogo, quel %GPMANAGER_FOUND% == truetest mi sembra molto sospetto. Non so su cosa sia impostata la variabile d'ambiente o come la stai impostando, ma dubito fortemente che il codice che hai mostrato produrrà il risultato che stai cercando.


Il seguente codice di esempio funziona bene per me:

@echo off

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

Si prega di notare alcuni dettagli specifici sul mio codice di esempio:

  • Lo spazio aggiunto tra la fine dell'istruzione condizionale e la parentesi di apertura.
  • Sto impostando @echo offper evitare di vedere tutte le istruzioni stampate sulla console durante l'esecuzione, e invece vedere solo l'output di quelle che iniziano specificamente echo.
  • Sto usando la ERRORLEVELvariabile incorporata solo come test. Leggi di più qui

1
Meglio usare se% ERRORLEVEL% == 0, poiché l'altra variante è sempre vera, perché SE ERRORLEVEL <N> è vero, se errorlevel è uguale o maggiore <N>, in questo caso "==" vengono ignorati
jeb

@ jeb: Penso che potresti aver perso il punto. L'uso ERRORLEVELnon è la risposta al suo problema. Stavo semplicemente pubblicando un esempio della sintassi corretta. Entrambe le forme sono accettabili in questo caso, proprio come lo sarebbero if 0 == 0o qualsiasi altra espressione banale. Ma in effetti, assicurati di aver compreso la differenza tra la variabile di ambiente %ERRORLEVEL%e l'interno ERRORLEVELdel processore dei comandi. Raymond Chen lo spiega bene qui su questo blog .
Cody Grey

Puoi avere un ALTRO SE?
xagyg

1
Aggiungendo al commento di @ mythofechelon, anche una parentesi di chiusura apparentemente innocua in un'istruzione REM farà terminare il blocco. es. Lanciarti REM This is a comment (or so I thought)nel IFblocco ti rovinerà.
rkagerer

2
Sia @mythofechelon che @rkagerer stanno sottolineando problemi specifici di una regola generale che le stringhe devono essere citate. Non dovresti mai codificarlo IF %somevar%==example_string2 dovrebbe essere sempre codice, quindi l'operando si risolve in IF "value_of_somevar"=="example_string2"per evitare caratteri speciali in entrambi gli operandi stringa che causano errori di sintassi nell'istruzione IF. I valori impostati dovrebbero essere sempre eseguiti come set "somevar=value_of_somevar" Tale sintassi ti consente di eseguire l'escape di caratteri speciali nei valori delle variabili, Nota che non intendo set somevar="value_of_somevar"
Salta R

15

Logicamente, la risposta di Cody dovrebbe funzionare. Tuttavia non credo che il prompt dei comandi gestisca logicamente un blocco di codice. Per quanto mi riguarda, non riesco a farlo funzionare correttamente con più di un singolo comando all'interno del blocco. Nel mio caso, test approfonditi hanno rivelato che tutti i comandi all'interno del blocco vengono memorizzati nella cache ed eseguiti simultaneamente alla fine del blocco. Questo ovviamente non produce i risultati attesi. Ecco un esempio semplificato:

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

Questo dovrebbe fornire a var3 il valore seguente:

blue_cheese

ma invece produce:

_

perché tutti e 3 i comandi vengono memorizzati nella cache ed eseguiti contemporaneamente all'uscita dal blocco di codice.

Sono stato in grado di superare questo problema riscrivendo il blocco if per eseguire un solo comando - goto - e aggiungendo alcune etichette. È goffo e non mi piace molto, ma almeno funziona.

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

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

:endif

8
L'utilizzo dell'espansione ritardata dovrebbe funzionare: utilizzare:set var3=!var1!_!var2!
Dracorat

4

Invece di questo goto pasticcio, prova a utilizzare la e commerciale & o la doppia e commerciale && (condizionale al livello di errore 0) come separatori di comando.

Ho corretto uno snippet di script con questo trucco, per riassumere, ho tre file batch, uno che chiama gli altri due dopo aver trovato a quali lettere sono state assegnate le unità di backup esterne. Lascio il primo file sull'unità esterna primaria in modo che le chiamate alla sua routine di backup abbiano funzionato correttamente, ma le chiamate al secondo hanno richiesto una modifica attiva dell'unità. Il codice seguente mostra come l'ho risolto:

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"
)

Perché diavolo questo viene svalutato? Questo è esattamente ciò di cui avevo bisogno.
ggb667

1
@ GCB667 - Per chiarire @Louis "ha scritto una" risposta "che non si riferisce al problema del perché l'istruzione IF non funzionava per il poster originale. Si riferiva a una risposta di" vinniejohnson "(che mancava anche il problema dei poster originali) .
Skip R

1

Mi sono imbattuto in questo articolo nei risultati restituiti da una ricerca relativa al comando IF in un file batch e non ho potuto resistere all'opportunità di correggere l'idea sbagliata che i blocchi IF siano limitati a singoli comandi. Di seguito è riportata una parte di uno script di comandi di Windows NT di produzione che viene eseguito quotidianamente sulla macchina su cui sto componendo questa risposta.

    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%
)

Forse i blocchi di due o più righe si applicano esclusivamente agli script di comando di Windows NT (file .CMD), perché una ricerca nella directory degli script di produzione di un'applicazione limitata ai file batch della vecchia scuola (.BAT), ha rivelato solo blocchi di un comando . Poiché l'applicazione è stata sottoposta a manutenzione estesa (il che significa che non sono attivamente coinvolto nel supportarla), non posso dire se ciò è dovuto al fatto che non avevo bisogno di più di una riga o che non potevo farle funzionare.

Indipendentemente da ciò, se quest'ultimo è vero, c'è una semplice soluzione alternativa; spostare le righe multiple in un file batch separato o in una subroutine di file batch. So che quest'ultimo funziona in entrambi i tipi di script.


0

Forse un po 'tardi, ma spero che sia un inferno:

@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
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.