Puis-je avoir un bloc IF dans le fichier batch DOS?


97

Dans un fichier batch DOS, nous ne pouvons avoir qu'une seule ligne si le corps de l'instruction? Je pense que j'ai trouvé quelque part que je pourrais utiliser ()pour un bloc if, tout comme celui {}utilisé dans les langages de programmation de type C, mais il n'exécute pas les instructions lorsque j'essaye ceci. Aucun message d'erreur non plus. Voici mon code:

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

Étrangement, ni «GP Manager est actif» ni «GP Manager est arrêté» ne sont imprimés lorsque j'exécute le fichier de commandes.


Peut-être que cela pourrait aider: commandwindows.com/batchfiles-branching.htm
esaj

Ya, ça aide. DOS est nul. Si je veux utiliser plusieurs instructions dans si ou sinon je dois utiliser && entre les instructions? ou y a-t-il une manière plus élégante?
Hugh Darling

Réponses:


140

Vous pouvez en effet placer create un bloc d'instructions à exécuter après un conditionnel. Mais vous avez une mauvaise syntaxe. Les parenthèses doivent être utilisées exactement comme indiqué:

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

Cependant, je ne pense pas qu'il existe une syntaxe intégrée pour les else-ifdéclarations. Vous devrez malheureusement créer des blocs d' ifinstructions imbriqués pour gérer cela.


Deuxièmement, ce %GPMANAGER_FOUND% == truetest me paraît très suspect. Je ne sais pas à quoi la variable d'environnement est définie ni comment vous la définissez, mais je doute fort que le code que vous avez montré produise le résultat que vous recherchez.


L'exemple de code suivant fonctionne très bien pour moi:

@echo off

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

Veuillez noter quelques détails spécifiques sur mon exemple de code:

  • L'espace ajouté entre la fin de l'instruction conditionnelle et la parenthèse ouvrante.
  • Je suis en train @echo offde ne pas voir toutes les instructions imprimées sur la console lors de leur exécution, et à la place de voir simplement la sortie de celles qui commencent spécifiquement par echo.
  • J'utilise la ERRORLEVELvariable intégrée comme test. En savoir plus ici

1
Mieux vaut utiliser si% ERRORLEVEL% == 0, car l'autre variante est toujours vraie, car SI ERRORLEVEL <N> est vrai, si errorlevel est égal ou supérieur <N>, les "==" sont ignorés dans ce cas
jeb

@jeb: Je pense que vous avez peut-être manqué le point. L'utilisation ERRORLEVELn'est pas la réponse à son problème. Je publiais simplement un exemple de la syntaxe appropriée. L'une ou l'autre forme est acceptable dans ce cas, tout comme le serait if 0 == 0ou toute autre expression triviale. Mais en effet, assurez-vous de bien comprendre la différence entre la variable d'environnement %ERRORLEVEL%et l'interne ERRORLEVELdu processeur de commande. Raymond Chen l'explique joliment ici sur ce blog .
Cody Gray

Pouvez-vous avoir un ELSE IF?
xagyg

1
En ajoutant au commentaire de @ mythofechelon, même une parenthèse de fermeture apparemment anodine dans une instruction REM mettra fin au blocage. Par exemple, REM This is a comment (or so I thought)jeter dans le IFbloc vous dérangera.
rkagerer

2
@Mythofechelon et @rkagerer signalent des problèmes spécifiques d'une règle générale selon laquelle les chaînes doivent être entre guillemets. Vous ne devez jamais coder, IF %somevar%==example_string2 il doit toujours être du code, donc l'opérande est résolu par IF "value_of_somevar"=="example_string2"pour éviter que les caractères spéciaux dans l'un ou l'autre des opérandes de chaîne ne provoquent des erreurs de syntaxe dans l' IFinstruction. Les valeurs que vous définissez doivent toujours être définies car set "somevar=value_of_somevar" Cette syntaxe vous permet d'échapper des caractères spéciaux dans les valeurs de variable. Remarque que je ne veux pas dire set somevar="value_of_somevar"
Skip R

15

Logiquement, la réponse de Cody devrait fonctionner. Cependant, je ne pense pas que l'invite de commande gère un bloc de code de manière logique. Pour la vie de moi, je ne peux pas faire fonctionner cela correctement avec plus d'une seule commande dans le bloc. Dans mon cas, des tests approfondis ont révélé que toutes les commandes du bloc sont mises en cache et exécutées simultanément à la fin du bloc. Cela ne donne évidemment pas les résultats escomptés. Voici un exemple simplifié à l'extrême:

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

Cela devrait fournir à var3 la valeur suivante:

blue_cheese

mais donne à la place:

_

car les 3 commandes sont mises en cache et exécutées simultanément à la sortie du bloc de code.

J'ai pu surmonter ce problème en réécrivant le bloc if pour n'exécuter qu'une seule commande - goto - et en ajoutant quelques étiquettes. C'est maladroit, et je n'aime pas beaucoup ça, mais au moins ça marche.

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

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

:endif

8
L'utilisation de l'expansion différée devrait fonctionner: utilisez:set var3=!var1!_!var2!
Dracorat

4

Au lieu de cela, essayez d'utiliser l'esperluette & ou la double esperluette && (conditionnelle au niveau d'erreur 0) comme séparateurs de commandes.

J'ai corrigé un extrait de script avec cette astuce, pour résumer, j'ai trois fichiers batch, l'un qui appelle les deux autres après avoir trouvé les lettres attribuées aux lecteurs de sauvegarde externes. Je laisse le premier fichier sur le lecteur externe principal pour que les appels à sa routine de sauvegarde fonctionnent correctement, mais les appels au second nécessitaient un changement de lecteur actif. Le code ci-dessous montre comment je l'ai corrigé:

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

Pourquoi diable ce vote est-il défavorable? C'est exactement ce dont j'avais besoin.
ggb667

1
@ GCB667 - Pour clarifier @Louis "a écrit une" réponse "qui ne se rapporte pas au problème de savoir pourquoi la déclaration IF ne fonctionnait pas pour l'affiche originale. Elle était liée à une réponse de" vinniejohnson "(qui a également manqué le problème des affiches originales) .
Skip R

1

Je suis tombé sur cet article dans les résultats renvoyés par une recherche liée à la commande IF dans un fichier batch, et je n'ai pas pu résister à l'opportunité de corriger l'idée fausse selon laquelle les blocs IF sont limités à des commandes uniques. Voici une partie d'un script de commande de production Windows NT qui s'exécute quotidiennement sur la machine sur laquelle je compose cette réponse.

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

Peut-être que les blocs de deux lignes ou plus s'appliquent exclusivement aux scripts de commande Windows NT (fichiers .CMD), car une recherche dans le répertoire des scripts de production d'une application qui est limitée aux fichiers batch old school (.BAT) n'a révélé que des blocs à une commande . Étant donné que l'application est entrée en maintenance étendue (ce qui signifie que je ne suis pas activement impliquée dans sa prise en charge), je ne peux pas dire si c'est parce que je n'avais pas besoin de plus d'une ligne ou que je ne pouvais pas les faire fonctionner.

Quoi qu'il en soit, si ce dernier est vrai, il existe une solution de contournement simple; déplacez les lignes multiples dans un fichier batch séparé ou un sous-programme de fichier batch. Je sais que ce dernier fonctionne dans les deux types de scripts.


0

Peut-être un peu tard, mais j'espère que ça va:

@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
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.