Tengo dos ejemplos de archivos por lotes muy simples:
Asignación de un valor a una variable:
@echo off
set FOO=1
echo FOO: %FOO%
pause
echo on
Lo cual, como se esperaba, da como resultado:
FOO: 1
Press any key to continue . . .
Sin embargo, si coloco las mismas dos líneas dentro de un bloque SI NO ES DEFINIDO:
@echo off
IF NOT DEFINED BAR (
set FOO=1
echo FOO: %FOO%
)
pause
echo on
Esto inesperadamente resulta en:
FOO:
Press any key to continue . . .
Esto no debería tener nada que ver con el IF, claramente el bloque se está ejecutando. Si defino BAR encima del if, solo se muestra el texto del comando PAUSE, como se esperaba.
¿Lo que da?
Pregunta de seguimiento: ¿Hay alguna forma de habilitar la expansión retrasada sin setlocal?
Si tuviera que llamar a este simple archivo por lotes de ejemplo desde otro, el ejemplo establece FOO, pero solo LOCALMENTE.
Por ejemplo:
testcaller.bat
@call test.bat
@echo FOO: %FOO%
@pause
test.bat
@setlocal EnableDelayedExpansion
@IF NOT DEFINED BAR (
@set FOO=1
@echo FOO: !FOO!
)
Esto muestra:
FOO: 1
FOO:
Press any key to continue . . .
En este caso, parece que tengo que habilitar la expansión retrasada en el LLAMADOR, lo que puede ser una molestia.
fuente
!
, use^^^!
(escape dos veces). De lo contrario, la función de "expansión retrasada" se lo comerá.El mismo comportamiento también ocurre cuando los comandos están en una sola línea (
&
es el separador de comandos):La explicación de Joey es mi favorita. Sin embargo,
enabledelayedexpansion
tenga en cuenta que eso no funciona en Windows NT 4.0 (y no estoy seguro acerca de Windows 2000).Acerca de su pregunta de seguimiento, no, no es posible
EnableDelayedExpansion
prescindirsetlocal
. Sin embargo, el comportamiento original que iba en contra de usted se puede utilizar para resolver ese segundo problema: el truco estáendlocal
en la misma línea donde establece nuevamente los valores de las variables que necesita.Aquí está tu
test.bat
modificado:Pero aquí hay otra solución a ese problema: use un procedimiento en el mismo archivo en lugar de un bloque en línea o un archivo externo.
fuente
Si no funciona de esa manera, es probable que haya retrasado la expansión de la variable de entorno. Puede desactivarlo
cmd /V:OFF
o usar signos de exclamación dentro de su if:fuente
Esto sucede porque su línea con
FOR
comando se evalúa solo una vez. Necesitas alguna forma de reevaluarlo. Puede simular una expansión demorada con elCALL
comando:fuente
Vale la pena señalar que sí funciona si es un solo comando en la misma línea.
p.ej
en realidad se establecerá
FOO
en 1. A continuación, puede hacer otra comprobación como:Oye, nunca dije que fuera bonito. Pero si no desea meterse con setlocal o el negocio de expansión demorada, es una solución rápida.
fuente
A veces, como lo hice en mi caso, cuando necesita ser compatible con sistemas heredados como los viejos servidores NT4 donde la expansión retrasada no funciona o por alguna razón no funciona, es posible que necesite una solución alternativa.
En caso de que use Expansión Delayd, también recomendó que se incluya al menos el check in en lote:
En caso de que solo desee un enfoque más legible y simple, aquí hay soluciones alternativas:
que funciona así:
y una solución cmd pura más:
funciona así:
y esto está lleno SI ENTONCES otra solución de sintaxis:
funciona así:
fuente