2
votes

I am trying to write a batch file to automate some routine Matlab processes. The batch file loops through from 0 to a set value (usually between 50 and 75) using the For /L structure. The script copies the main Matlab script to the subfolder and runs it. The batch would normally continue onward so I put a :loop to wait until the Matlab ends.

echo off
setlocal EnableDelayedExpansion

REM The format is matlab_auto.in (max value). 
For /L %%G in (0,1,%1) do (
REM Sanity check
echo 1 %%G

REM Create Outputs folder if non-existent
if not exist Outputs md Outputs

REM Copy .m file into deg folder and cd to folder
copy values_calc.m %%Gsort\values_calc.m
cd %%Gsort
echo Got to folder

    REM Running .m script and sanity check
echo 2 %%G
matlab -nosplash -nodesktop -noFigureWindows -logfile output.log -r "run('values_calc.m');"
echo 3 %%G

REM Waiting for matlab to finish
:loop
tasklist /fi "imagename eq MATLAB.exe" |find ":" > nul
echo 4 %%G
if errorlevel 1 goto loop
echo Finished Matlab  
echo 5 %%G

REM Copy .m outputs into outputs folder, ignoring confirmation
copy Output_*.* ..\Outputs /Y
echo Copied outputs 

REM Sanity check and return home
echo 6 %%G
cd %~dp0
echo Home again

)

The problem I'm having is that when it ends after the first iteration of the For loop. Echo 1, 2, 3 are 0. Echo 4 shows 0 the first time through :loop but then it shows %G for the remainder of the loops and at Echos 5 and 6. It also does not continue into further iterations of the For loop. I'm assuming this is because %%G is no longer a number (or in the range specified).

I have tried implementing a call subroutine to use the goto outside the loop but then it opens the Matlab dozens of times, crashing the computer.

Any insight or advice is appreciated. Thank you.

EDIT: Changed the :: for commenting to REM. It did not resolve this issue but looks better.

EDIT 2: I have a test case that demonstrates the problem. Its something with the :loop or goto. echo off setlocal EnableDelayedExpansion

for /l %%G in (0,1,5) do (
    :loop
    echo %%G
    pause
    if %%G==0 goto loop
)
1
Off the top of my head and without actually trying anything, I know that for loops absolutely hate :: as comments. Try replacing them with REM commands. - SomethingDark

1 Answers

2
votes

Yes. The execution of a GOTO command cancel any active (pending) FOR or IF commands that may be nested inside parentheses at any level. This way, the commands placed below the :loop label are executed inside the FOR context the first time, but after the goto command they are executed as if they were placed outside the FOR loop! The way to solve this problem is extracting the code below the label into a subroutine and then call :loop in the FOR.

echo off
setlocal EnableDelayedExpansion

REM The format is matlab_auto.in (max value). 
For /L %%G in (0,1,%1) do (
   REM Sanity check
   echo 1 %%G

   REM Create Outputs folder if non-existent
   if not exist Outputs md Outputs

   REM Copy .m file into deg folder and cd to folder
   copy values_calc.m %%Gsort\values_calc.m
   cd %%Gsort
   echo Got to folder

   REM Running .m script and sanity check
   echo 2 %%G
   matlab -nosplash -nodesktop -noFigureWindows -logfile output.log -r "run('values_calc.m');"
   echo 3 %%G

   REM Waiting for matlab to finish
   call :loop
   echo Finished Matlab  
   echo 5 %%G

   REM Copy .m outputs into outputs folder, ignoring confirmation
   copy Output_*.* ..\Outputs /Y
   echo Copied outputs 

   REM Sanity check and return home
   echo 6 %%G
   cd %~dp0
   echo Home again

)
goto :EOF

:loop
tasklist /fi "imagename eq MATLAB.exe" |find ":" > nul
REM echo 4 %%G
if errorlevel 1 goto loop
exit /B