I suggest the following with command REM commented batch file for this task.
@ECHO OFF
SETLOCAL EnableExtensions DisableDelayedExpansion
REM Make the batch file directory the current working directory.
PUSHD "%~dp0" || EXIT /B
REM Run tests, starting with test# given as argument.
IF "%~1" == "" (SET "testnum=0") ELSE SET "testnum=%~1"
ECHO Argument 1 is: %1
ECHO Start test = %testnum%
REM Process all non-hidden subdirectories in the batch file directory of
REM which name begins with the string test. Use FOR /F command to get just
REM the number of the subdirectory assigned to the loop variable J which
REM must not have leading zeros. Check next if that number is greater or
REM equal the number assigned to the variable testnum. In this case check
REM if the subdirectory contains the batch file with name run.bat. If this
REM condition is true, make the subdirectory the current working directory,
REM call the batch file run.bat in the subdirectory, and then restore the
REM batch file directory as the current working directory.
FOR /D %%I IN (test*) DO FOR /F "delims=ESTest" %%J IN ("%%I") DO IF %%J GEQ %testnum% IF EXIST "%%I\run.bat" (
PUSHD "%%I"
CALL run.bat
POPD
)
REM Restore the initial current working directory on start of the batch file.
POPD
REM Restore the initial local environment on start of the batch file.
ENDLOCAL
In which order the subdirectories matched by the wildcard pattern test* are processed depends on the file system. NTFS and ReFS store file system entries sorted alphabetically (locale specific as on creation of the partition) while FAT32 or exFAT store file system entries according to last creation/modification with the newest created/modified files/directories at bottom of the list.
Example: The subdirectories are created in this order:
test1
test4
test3
test2
test121
test14
NTFS and ReFS store internally the directory names in the following order:
test1
test121
test14
test4
test3
test2
FAT32 and exFAT store internally the directory names in the following order:
test1
test4
test3
test2
test121
test14
The directories names matched by the wildcard pattern test* are returned by the file system to cmd.exe processing the batch file in the order as stored in file system. The batch file above does not contain any commands to first get the list of directory names loaded into the memory of cmd.exe in an alphanumeric order as the Windows File Explorer displays them. Windows File Explorer displays the directories in the following order:
test1
test2
test3
test4
test14
test121
In does not really matter in which order run.bat is executed as long as all run.bat in a test* subdirectory with a number greater or equal the number specified on execution of the main batch file as first argument are called by the main batch file.
More command lines would be necessary to get the directory names first sorted alphanumeric like Windows File Explorer does before processing the directory names with a FOR loop.
An alphanumeric sort with test1, test2 … test9, test10, test11 … test99, test100, test101 … is not trivial as there is no Windows command which supports such a sort.
A processing in correct alphanumeric order would be easier to achieve with all subdirectories having the same number of digits, i.e. test001, test002 … test009, test010, test011 … test099, test100, test101 …
The batch file for such directory names could be:
@ECHO OFF
SETLOCAL EnableExtensions DisableDelayedExpansion
REM Make the batch file directory the current working directory.
PUSHD "%~dp0" || EXIT /B
REM Run tests, starting with test# given as argument.
IF "%~1" == "" (SET "testnum=0") ELSE SET "testnum=%~1"
ECHO Argument 1 is: %1
ECHO Start test = %testnum%
REM Process alphabetic ordered by name all non-hidden subdirectories not
REM being a junction or symbolic link in the batch file directory of which
REM name begins with the string test. The subdirectory names must have all
REM the same length, i.e. the number of digits must be the same in all the
REM directory names. Use FOR /F command to get just the number of the
REM subdirectory without leading zeros assigned to the loop variable J.
REM Check next if that decimal interpreted number is greater or equal
REM the number assigned to the variable testnum. In this case check if
REM the subdirectory contains the batch file with name run.bat. If this
REM condition is true, make the subdirectory the current working directory,
REM call the batch file run.bat in the subdirectory, and then restore the
REM batch file directory as the current working directory.
FOR /F %%I IN ('DIR test* /AD-H-L /B /ON 2^>NUL') DO FOR /F "tokens=* delims=0ESTest" %%J IN ("%%I") DO IF %%J GEQ %testnum% IF EXIST "%%I\run.bat" (
PUSHD "%%I"
CALL run.bat
POPD
)
REM Restore the initial current working directory on start of the batch file.
POPD
REM Restore the initial local environment on start of the batch file.
ENDLOCAL
The following batch file calls run.bat in correct order for the directory naming schemes:
test1, test2 … test9, test10, test11 … test99, test100, test101 …
test001, test002 … test009, test010, test011 … test099, test100, test101 …
But it does not call run.bat in the correct numeric order if the directory names are a mixture of both naming schemes, i.e. some directory names with a number less than 100 are without and some with leading zeros.
@ECHO OFF
SETLOCAL EnableExtensions DisableDelayedExpansion
REM Make the batch file directory the current working directory.
PUSHD "%~dp0" || EXIT /B
REM Run tests, starting with test# given as argument.
IF "%~1" == "" (SET "testnum=0") ELSE SET "testnum=%~1"
ECHO Argument 1 is: %1
ECHO Start test = %testnum%
REM Process alphanumeric ordered by name all non-hidden subdirectories not
REM being a junction or symbolic link in the batch file directory of which
REM name begins with the string test. Use FOR /F command to get just the
REM number of the subdirectory without leading zeros assigned to the loop
REM variable J. Check next if that decimal interpreted number is greater
REM or equal the number assigned to the variable testnum. In this case check
REM if the subdirectory contains the batch file with name run.bat. If this
REM condition is true, make the subdirectory the current working directory,
REM call the batch file run.bat in the subdirectory, and then restore the
REM batch file directory as the current working directory.
FOR /F %%I IN ('DIR test* /AD-H-L /B /ON 2^>NUL ^| %SystemRoot%\System32\findstr.exe /I /R "^test[123456789]$" ^& DIR test* /AD-H-L /B /ON 2^>NUL ^| %SystemRoot%\System32\findstr.exe /I /R "^test[0123456789][0123456789]$" ^& DIR test* /AD-H-L /B /ON 2^>NUL ^| %SystemRoot%\System32\findstr.exe /I /R "^test[0123456789][0123456789][0123456789]$"') DO FOR /F "tokens=* delims=0ESTest" %%J IN ("%%I") DO IF %%J GEQ %testnum% IF EXIST "%%I\run.bat" (
PUSHD "%%I"
CALL run.bat
POPD
)
REM Restore the initial current working directory on start of the batch file.
POPD
REM Restore the initial local environment on start of the batch file.
ENDLOCAL
I recommend to read further:
- Why is no string output with 'echo %var%' after using 'set var = text' on command line?
It explains the difference between SET testnum="0" with first " after the equal sign and SET "testnum=0" with first " left to the variable name. SET testnum="0" is wrong for this use case using %testnum% in an integer comparison with GEQ.
- Symbol equivalent to NEQ, LSS, GTR, etc. in Windows batch files
It explains the reason why IF %J% GEQ %testnum% with SET testnum="0" resulted in a string instead of an integer comparison on execution of the batch file in the question while IF %%J GEQ %testnum% and SET "testnum=0" in the batch files posted in this answer really results in an integer comparison. There is also explained why it is necessary to remove leading zeros from the number by the second batch file to avoid interpreting 014 as octal number (decimal 12) and 008 or 092 or other numbers with a leading zero with digit 8 or 9 as invalid octal number and therefore as decimal number 0.