2011-02-13 8 views
78

En un archivo por lotes DOS, solo podemos tener 1 línea si el cuerpo de la declaración es? Creo que encontré en algún lugar que podría usar () para un bloque if como el {} usado en lenguajes de programación similares a C, pero no está ejecutando las declaraciones cuando intento esto. Sin mensaje de error tampoco. Este mi código:¿Puedo tener un bloque IF en el archivo por lotes de DOS?

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

extraño ni "Administrador GP es arriba" ni "Administrador GP es abajo" que se imprime cuando ejecuto el archivo por lotes.

+0

Quizás esto ayude: http://commandwindows.com/batchfiles-branching.htm – esaj

+0

Ya, eso ayuda. DOS apesta. Si quiero usar varias declaraciones en if o else, tengo que usar && between statements? o hay una manera más elegante? –

Respuesta

108

De hecho, puede colocar crear un bloque de instrucciones para ejecutar después de un condicional. Pero tienes la sintaxis equivocada. Los paréntesis se deben utilizar exactamente como se muestra:

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

Sin embargo, no creo que haya ninguna incorporada sintaxis para else-if declaraciones. Desgraciadamente, necesitará crear bloques anidados de instrucciones if para manejar eso.


En segundo lugar, esa %GPMANAGER_FOUND% == true prueba parece poderosa sospechosa para mí. No sé en qué se configura la variable de entorno ni cómo la configura, pero dudo mucho que el código que ha mostrado produzca el resultado que está buscando.


El siguiente código de ejemplo funciona bien para mí:

@echo off 

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

Tenga en cuenta algunos detalles específicos acerca de mi código de ejemplo:

  • El mayor espacio entre el final de la sentencia condicional, y el paréntesis de apertura.
  • me he fijado @echo off para no ver todo de las declaraciones impresas a la consola mientras se ejecutan, y en lugar de simplemente ver la salida de los que comienzan específicamente con echo.
  • Estoy usando la variable incorporada ERRORLEVEL solo como una prueba. Leer más here
+0

Mejor uso si% ERRORLEVEL% == 0, como la otra variante es siempre verdadera, porque IF ERRORLEVEL es verdadero, si errorlevel es igual o mayor , los "==" se ignoran en este caso – jeb

+0

@jeb: Creo es posible que haya perdido el punto. Usar 'ERRORLEVEL' no es la respuesta a su problema. Simplemente estaba publicando un ejemplo de la sintaxis adecuada. * Cualquiera de las * formas es aceptable en este caso, al igual que 'si 0 == 0' o cualquier otra expresión trivial. Pero, de hecho, asegúrese de comprender la diferencia entre la variable de entorno '% ERRORLEVEL%' y el 'ERRORLEVEL' interno del procesador de comandos. Raymond Chen lo explica muy bien [aquí en este blog] (http://blogs.msdn.com/b/oldnewthing/archive/2008/09/26/8965755.aspx). –

+0

¿Puedes tener un ELSE IF? – xagyg

12

Lógicamente, la respuesta debe trabajo de Cody. Sin embargo, no creo que el símbolo del sistema maneje un bloque de código lógicamente. Por mi vida, no puedo lograr que funcione correctamente con más de un comando dentro del bloque. En mi caso, pruebas exhaustivas revelaron que todos los comandos dentro del bloque se almacenan en caché y se ejecutan simultáneamente al final del bloque. Esto, por supuesto, no produce los resultados esperados. Aquí es un ejemplo muy simplificado:

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

Este debería proporcionar var3 con el siguiente valor:

blue_cheese 

pero en su lugar se obtiene:

_ 

porque todos los 3 comandos se almacenan en caché y ejecutados simultáneamente al salir del bloque de código.

Pude solucionar este problema volviendo a escribir el bloque if para ejecutar solo un comando - goto - y agregar algunas etiquetas. Es torpe, y no me gusta mucho, pero al menos funciona.

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

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

:endif 
+7

Usar la expansión retrasada debería trabajo: uso: 'set var3 =! var1! _! var2!' – Dracorat

0

Tal vez un poco tarde, pero espero que hellps:

@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 
-1

En lugar de este lío Goto, intente utilizar el signo & o signo doble & & (condicional a ErrorLevel 0) como separadores de mando.

He arreglado un fragmento de script con este truco, para resumir, tengo tres archivos de proceso por lotes, uno que llama a los otros dos después de haber encontrado las letras que las unidades de respaldo externas han sido asignadas. Dejo el primer archivo en la unidad externa principal para que las llamadas a su rutina de copia de seguridad funcionen bien, pero las llamadas a la segunda requieren un cambio de unidad activo. El código siguiente muestra cómo me fijo:

para %% b en (yz DEFGHIJKLMNOPQRSTUVWX) hacer ( si existe "%% b: \ Backup.cmd" %% b: & LLAMADA "%% b: \ Backup .cmd " )

+0

¿Por qué diablos es esto downvoted? Esto es exactamente lo que necesitaba. – ggb667

+0

@ GCB667 - Para aclarar que @Louis "escribió una" respuesta "que no se relaciona con el problema de por qué la declaración IF no funcionaba para el póster original. Se relacionaba con una respuesta de" vinniejohnson "(que también omitía el problema de los carteles originales)) –

0

Me encontré con este artículo en los resultados devueltos por una búsqueda relacionada con el comando IF en un archivo por lotes, y no pude resistir la oportunidad de corregir la idea errónea de que los bloques IF están limitados a solo comandos. A continuación se muestra una parte de un script de comandos de Windows NT de producción que se ejecuta a diario en la máquina en la que estoy redactando esta respuesta.

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

Quizás bloques de dos o más líneas se aplica exclusivamente a los scripts de comandos de Windows NT (.cmd), debido a que una búsqueda del directorio de scripts de producción de una aplicación que se limita a los lotes de edad escolar archivos (.bat) , reveló solo bloques de un comando. Dado que la aplicación se ha destinado al mantenimiento extendido (lo que significa que no participo activamente en su apoyo), no puedo decir si eso se debe a que no necesitaba más de una línea o si no podía hacer que funcionara.

Independientemente, si esto último es cierto, hay una solución simple; mueva las líneas múltiples a un archivo por lotes separado o a una subrutina de archivo por lotes. Sé que este último funciona en ambos tipos de scripts.

Cuestiones relacionadas