This article addresses one specific use case for recursion in batch: Recursively looping through a directory (also called a folder) and its sub directories.
Normally, this is a pain, and it took me a while to come up with an algorithm that works.
For recursion to work correctly, you need:
a) Subroutines, and
b) Local variables.
CMD.EXE supports the first one, but local variables are a pain: You can only use SETLOCAL/ENDLOCAL, which prevents any information to be returned to any calling level (except the ERRORLEVEL).
Here is a solution, implemented as a script that recursively deletes empty sub directories of the current directory, and traverses all the way down the directory tree:
@echo off
rem This pushd is to make sure the script always returns to
rem the directory it was called from
pushd .
set ABORT=
call :Process_Dir
popd
exit /b
:Process_Dir
rem If ABORT is set, do not continue, but unwind the call stack.
rem Errorlevel 1 makes sure the rd command is not attempted
if defined ABORT exit /b 1
rem First, process the subdirectories through recursion
for /d %%I in (*.*) do call :Recurse "%%~I"
rem If ABORT is set, do not continue, but unwind the call stack
if defined ABORT exit /b 1
rem Next, count the file items in the current directory
rem Actually, I am only interested if there are 0, or 1 (or more)
rem items in the directory
set CNT=0
for /f %%I in ('dir /b') do set CNT=1
rem Return the CNT flag as an errorlevel to the calling sub
exit /b %CNT%
:Recurse
rem If the CD fails, set ABORT and exit immed
rem !!If the following line shows &, replace it with a real ampersand - it's a
rem !! limitation of the syntax highlighter on our web site
cd "%~1"||(set ABORT=Y&exit /b)
call :Process_Dir
set RESULT=%ERRORLEVEL%
if defined ABORT exit /b
cd ..
rem Based on the result of Process_Dir, delete the subdirectory
if %RESULT% equ 0 rd "%~1"
exit /b
That’s it!
Share