I have two .bat files, both use delayed expansion, so that I can set variables within for loops.
The example below is greatly simplified just to show the problem
Script one.bat
@echo off
setlocal enableextensions
setlocal enabledelayedexpansion
set j=0
for /L %%i in (1,1,2) do (
set j=%%i
set /A j=!j! + 1
echo %%i !j!
two.bat
echo %%i !j!
)
Script two.bat
@echo off
setlocal enableextensions
setlocal enabledelayedexpansion
echo Hello World
exit /B 0
On return from two.bat variable !j! is lost and echo is turned back on.
J:\>one
1 2
Hello World
1 !j!
J:\>(
set j=2
set /A j=!j! + 1
echo 2 !j!
two.bat
echo 2 !j!
)
Missing operator.
2 !j!
Hello World
2 !j!
Yes I could make two.bat a sub-routine in one.bat but its hundred of lines long and I dont want to have to maintain two copies of the same logic
What am I missing here ?
Your assumption is wrong that execution returns from file
two.bat, because that is only the case when you are using thecallcommand1.The batch file
one.batrunstwo.batwithin a parenthesised block of code, which is already in a command stack2, so the block is (kind of) finished before terminating execution.Your output perfectly illustrates what happens (therefore I commented it here):
To prove whether execution happens under batch file or Command Prompt context, just place
set /A jin the loop body inone.batas the last command, so you will get an additional output0after the output1 !j!and the second2 !j!, becauseset /Adoes not return anything in batch file context, but it outputs the (last) result (without a trailing line-break) in Command Prompt context; the value of0shows thatjis no longer set.1) There are a few exceptions: the called batch file is involved in a pipe, or it is run and parsed by a
for /Floop, because the batch file runs in a newcmd.exeinstance in such cases.2) The same would be true if the called batch file was involved in a line with concatenated commands, hence something like
two.bat & echo Finewould echoFineupon execution oftwo.bat.