SI … O SI … en un archivo de lote de Windows

¿Hay alguna forma de escribir una statement condicional IF o IF en un archivo por lotes de Windows?

Por ejemplo:

IF [%var%] == [1] OR IF [%var%] == [2] ECHO TRUE 

La solución zmbq es buena, pero no se puede usar en todas las situaciones, como dentro de un bloque de código como un ciclo FOR DO (…).

Una alternativa es usar una variable indicadora. Inicialícela para que no esté definida, y luego defínala solo si alguna de las condiciones O es verdadera. Luego, use IF IF DEFINED como prueba final; no es necesario usar la expansión retardada.

 FOR ..... DO ( set "TRUE=" IF cond1 set TRUE=1 IF cond2 set TRUE=1 IF defined TRUE ( ... ) else ( ... ) ) 

Podría agregar la lógica ELSE IF que utiliza arasmussen con el argumento de que podría funcionar un poquito más rápido si la primera condición es verdadera, pero nunca me molesto.

Adición : esta es una pregunta duplicada con respuestas casi idénticas al uso de un OR en una instrucción IF WinXP Batch Script

Adenda final : casi me olvido de mi técnica favorita para probar si una variable es cualquiera de una lista de valores. Inicialice una variable de prueba que contenga una lista delimitada de valores aceptables, y luego use buscar y reemplazar para probar si su variable está dentro de la lista. Esto es muy rápido y usa un código mínimo para una lista arbitrariamente larga. Requiere expansión retrasada (o el truco CALL %% VAR %%). Además, la prueba es CASE INSENSITIVE.

 set "TEST=;val1;val2;val3;val4;val5;" if "!TEST:;%VAR%;=!" neq "!TEST!" (echo true) else (echo false) 

Lo anterior puede fallar si VAR contiene = , por lo que la prueba no es infalible.

Si realiza la prueba dentro de un bloque donde se necesita una expansión retardada para acceder al valor actual de VAR, entonces

 for ... do ( set "TEST=;val1;val2;val3;val4;val5;" for /f %%A in (";!VAR!;") do if "!TEST:%%A=!" neq "!TEST!" (echo true) else (echo false) ) 

PUEDEN SER NECESARIAS opciones como “delims =” dependiendo de los valores esperados dentro de VAR

La estrategia anterior puede hacerse confiable incluso con = en VAR agregando un poco más de código.

 set "TEST=;val1;val2;val3;val4;val5;" if "!TEST:;%VAR%;=!" neq "!TEST!" if "!TEST:;%VAR%;=;%VAR%;"=="!TEST!" echo true 

Pero ahora hemos perdido la capacidad de proporcionar una cláusula ELSE a menos que agreguemos una variable indicadora. El código ha comenzado a parecer un poco “feo”, pero creo que es el método confiable que mejor funciona para probar si VAR es cualquiera de una cantidad arbitraria de opciones insensibles a mayúsculas y minúsculas.

Finalmente, hay una versión más simple que creo que es un poco más lenta porque debe realizar un IF para cada valor. Aacini proporcionó esta solución en un comentario a la respuesta aceptada en el enlace mencionado anteriormente

 for %%A in ("val1" "val2" "val3" "val4" "val5") do if "%VAR%"==%%A do echo true 

La lista de valores no puede incluir * o? caracteres, y los valores y %VAR% no deben contener comillas. Las comillas generan problemas si %VAR% también contiene espacios o caracteres especiales como ^ , & , etc. Otra limitación de esta solución es que no proporciona la opción de una cláusula ELSE a menos que se agregue una variable indicadora. Las ventajas son que puede ser sensible a mayúsculas y minúsculas o insensible dependiendo de la presencia o ausencia de la opción IF /I

No lo creo. Simplemente use dos IF y GOTO la misma etiqueta:

 IF cond1 GOTO foundit IF cond2 GOTO foundit ECHO Didn't found it GOTO end :foundit ECHO Found it! :end 

Gracias por esta publicación, me ayudó mucho.

No sé si puede ayudar pero tuve el problema y gracias a ti encontré lo que creo que es otra forma de resolverlo en base a esta equivalencia booleana:

“A o B” es lo mismo que “no (no A y no B)”

Así:

 IF [%var%] == [1] OR IF [%var%] == [2] ECHO TRUE 

Se convierte en:

 IF not [%var%] == [1] IF not [%var%] == [2] ECHO FALSE 

Incluso si esta pregunta es un poco más antigua:

Si quieres usar if cond1 or cond 2 , no deberías usar loops complicados o cosas así.

Simple proporciona ambos ifs uno después del otro combinado con goto – eso es un implícito o.

 //thats an implicit IF cond1 OR cond2 OR cond3 if cond1 GOTO doit if cond2 GOTO doit if cond3 GOTO doit //thats our else. GOTO end :doit echo "doing it" :end 

Sin ir más allá de una acción “in situ”, puede ejecutar la acción 3 veces, si TODAS las condiciones coinciden.

No hay IF OR o ELIF o ELSE IF en Lote, sin embargo …

Intente anidar los otros IF dentro del ELSE del IF anterior.

 IF  ( .... ) ELSE ( IF  ( ...... ) ELSE ( IF  ( .... ) ELSE ( ) ) 

El objective se puede lograr mediante el uso indirecto de IF.

A continuación se muestra un ejemplo de una expresión compleja que puede escribirse de manera bastante concisa y lógica en un lote de CMD, sin tags incoherentes ni GOTO.

Los bloques de código entre () corchetes son manejados por CMD como un tipo (patético) de subshell. Cualquier código de salida que salga de un bloque se usará para determinar el valor verdadero / falso que juega el bloque en una expresión booleana más grande. Se pueden construir expresiones booleanas arbitrariamente grandes con estos bloques de código.

Ejemplo simple

Cada bloque se resuelve en verdadero (es decir, ERRORLEVEL = 0 después de que se haya ejecutado la última instrucción en el bloque) / false, hasta que se haya determinado el valor de toda la expresión o salte el control (por ejemplo, a través de GOTO):

  ((DIR c:\xsgdde /w) || (DIR c:\ /w)) && (ECHO -=BINGO=-) 

Ejemplo complejo

Esto resuelve el problema planteado inicialmente. Varias declaraciones son posibles en cada bloque, pero en el || || || expresión es preferible ser conciso para que sea lo más legible posible. ^ es un carácter de escape en lotes CMD y cuando se coloca al final de una línea escapará de la EOL e indicará a CMD que continúe leyendo el lote actual de declaraciones en la siguiente línea.

 @ECHO OFF SETLOCAL ENABLEDELAYEDEXPANSION ( (CALL :ProcedureType1 ab) ^ || (CALL :ProcedureType2 sgd) ^ || (CALL :ProcedureType1 cc) ) ^ && ( ECHO -=BINGO=- GOTO :EOF ) ECHO -=no bingo for you=- GOTO :EOF :ProcedureType1 IF "%~1" == "%~2" (EXIT /B 0) ELSE (EXIT /B 1) GOTO :EOF (this line is decorative as it's never reached) :ProcedureType2 ECHO :ax:xa:xx:aa:|FINDSTR /I /L /C:":%~1:">nul GOTO :EOF 

Es posible usar una función que evalúa la lógica OR y devuelve un solo valor.

 @echo off set var1=3 set var2=5 call :logic_or orResult "'%var1%'=='4'" "'%var2%'=='5'" if %orResult%==1 ( echo At least one expression is true ) ELSE echo All expressions are false exit /b :logic_or  expression1 [[expr2] ... expr-n] SETLOCAL set "logic_or.result=0" set "logic_or.resultVar=%~1" :logic_or_loop if "%~2"=="" goto :logic_or_end if %~2 set "logic_or.result=1" SHIFT goto :logic_or_loop :logic_or_end ( ENDLOCAL set "%logic_or.resultVar%=%logic_or.result%" exit /b ) 
 If %x%==1 ( If %y%==1 ( :: both are equal to 1. ) ) 

Eso es para verificar si múltiples variables tienen el mismo valor. Aquí está para cualquiera de las variables.

 If %x%==1 ( :: true ) If %x%==0 ( If %y%==1 ( :: true ) ) If %x%==0 ( If %y%==0 ( :: False ) ) 

Solo pensé en eso fuera de mi cabeza. Podría compactarlo más.

Me doy cuenta de que esta pregunta es antigua, pero quería publicar una solución alternativa en caso de que alguien más (como yo) encontrara este hilo mientras tenía la misma pregunta. Pude evitar la falta de un operador OR haciendo eco de la variable y usando findtr para validar.

 for /f %%v in ('echo %var% ^| findstr /x /c:"1" /c:"2"') do ( if %errorlevel% equ 0 echo true ) 

Si bien la respuesta de dbenham es bastante buena, confiar en IF DEFINED puede generar muchos problemas si la variable que está comprobando no es una variable de entorno . Las variables de script no reciben este tratamiento especial.

Si bien esto puede parecer una BS ridícula indocumentada, haciendo una simple consulta shell de IF con IF /? revela eso,

El condicional DEFINIDO funciona igual que EXISTE, excepto que toma un nombre de variable de entorno y devuelve verdadero si se define la variable de entorno .

En lo que respecta a responder a esta pregunta, ¿hay alguna razón para no usar simplemente una bandera después de una serie de evaluaciones? A mí me parece que es el control OR más flexible, tanto en lo que respecta a la lógica subyacente como a la legibilidad. Por ejemplo:

 Set Evaluated_True=false IF %condition_1%==true (Set Evaluated_True=true) IF %some_string%=="desired result" (Set Evaluated_True=true) IF %set_numerical_variable% EQ %desired_numerical_value% (Set Evaluated_True=true) IF %Evaluated_True%==true (echo This is where you do your passing logic) ELSE (echo This is where you do your failing logic) 

Obviamente, pueden ser cualquier tipo de evaluación condicional, pero solo estoy compartiendo algunos ejemplos.

Si quisieras tener todo en una línea, por escrito, podrías simplemente encadenarlos con && como:

 Set Evaluated_True=false IF %condition_1%==true (Set Evaluated_True=true) && IF %some_string%=="desired result" (Set Evaluated_True=true) && IF %set_numerical_variable% EQ %desired_numerical_value% (Set Evaluated_True=true) IF %Evaluated_True%==true (echo This is where you do your passing logic) ELSE (echo This is where you do your failing logic) 

Nunca existió para trabajar.

Uso si no existe g: xyz / what goto h: Else xcopy c: current / files g: bu / current Hay modificadores / a, etc. No estoy seguro de cuáles. Ordenador portátil en la tienda. Y la computadora en la oficina. No estoy ahí.

Nunca obtuve archivos por lotes para trabajar por encima de Windows XP

Un simple “FOR” se puede usar en una sola línea para usar una condición “o”:

 FOR %%a in (item1 item2 ...) DO IF {condition_involving_%%a} {execute_command} 

Aplicado a su caso:

 FOR %%a in (1 2) DO IF %var%==%%a ECHO TRUE 

Al darme cuenta de esto es una vieja pregunta, las respuestas me ayudaron a encontrar una solución para probar los argumentos de línea de comando en un archivo por lotes; así que quería publicar mi solución también en caso de que alguien más estuviera buscando una solución similar.

Lo primero que debo señalar es que estaba teniendo problemas para obtener instrucciones IF … ELSE para trabajar dentro de una cláusula FOR … DO. Resulta que (gracias a dbenham por señalar inadvertidamente esto en sus ejemplos) la instrucción ELSE no puede estar en una línea separada de las parens de cierre.

Entonces en vez de esto:

 FOR ... DO ( IF ... ( ) ELSE ( ) ) 

Cuál es mi preferencia por legibilidad y razones estéticas, tienes que hacer esto:

 FOR ... DO ( IF ... ( ) ELSE ( ) ) 

Ahora la instrucción ELSE no retorna como un comando no reconocido.

Finalmente, esto es lo que estaba intentando hacer: quería poder pasar varios argumentos a un archivo de proceso por lotes en cualquier orden, ignorando el caso y reportando / fallando sobre argumentos indefinidos pasados. Así que aquí está mi solución …

 @ECHO OFF SET ARG1=FALSE SET ARG2=FALSE SET ARG3=FALSE SET ARG4=FALSE SET ARGS=(arg1 Arg1 ARG1 arg2 Arg2 ARG2 arg3 Arg3 ARG3) SET ARG= FOR %%A IN (%*) DO ( SET TRUE= FOR %%B in %ARGS% DO ( IF [%%A] == [%%B] SET TRUE=1 ) IF DEFINED TRUE ( SET %%A=TRUE ) ELSE ( SET ARG=%%A GOTO UNDEFINED ) ) ECHO %ARG1% ECHO %ARG2% ECHO %ARG3% ECHO %ARG4% GOTO END :UNDEFINED ECHO "%ARG%" is not an acceptable argument. GOTO END :END 

Tenga en cuenta que esto solo informará sobre el primer argumento fallido. Entonces, si el usuario pasa más de un argumento inaceptable, solo se les informará sobre el primero hasta que se corrija, luego el segundo, etc.