Recursion in Batch Files

There are five main approaches to recursion, some with variants:

vector absolute on non-null argument
@echo off
  if not "%1" == "" goto pass2
and it's variant
vector absolute on null argument

  @echo off
  if "%1" == "" goto pass2
vector to argument on non-null argument

  @echo off
  if not "%1" == "" goto %1
vector absolute on flag

  @echo off
  if "%1" == "}{" goto pass2
vector to argument on flag

  @echo off
  if "%1" == "}{" goto %2
and the variant in which the GOTO command is also an argument

  @echo off
  if "%1" == "}{" %2 %3
where %2 contains the command and %3 the target - this is more abstract, and lead me to the third approach:
vector or not, with the entire command being variable

  @echo off
  %1 %2
or

  @echo off
  %fork%
Note that in the last two cases, not even the existence, let alone the nature of the command is determined when the program begins. This approach is totally virtual - the command can be nothing at all, as would usually, but not always, be the case on the first pass; it can be something other than a recursion vector - for example, a command to call another batch file or executable; or it can be a vector to code within the program, determined from outside on the first pass and from its own code on subsequent passes. It may not look like it, but this is deep magic. More on this later, after examining the simpler cases.

The vector absolute on null or non-null argument are the simplest and least useful - there can be only one possible target, which limits the recursion to just two levels. However, there is the possibility of combining the non-null case with one or another of the other cases to make compound recursion vectoring in which the presence of any argument directs the program flow to a place in the code where more detailed analysis of the arguments takes place:


 @echo off
 if not "%1" == "" goto vector
  ... initialization code goes here
  ... something call %0 }{ foo
  ... or 
  ... something call %0 foo
 goto end
 :vector
 if %1 == }{ goto %2
 REM else
 goto %1
  ... various code blocks and labels go here
 :end
I see no advantage in this over the totally variable construct.
Note: the use of "}{" as a marker is something I introduced to the MSDOS forum on Compuserve a couple of years before I introduced the totally variable syntax, and has no significance beyond its rarity - which makes it extremely unlikely that the marker would duplicate a real argument needed by any batch file. If you have a case in which it does, just change the marker - the only requirement is that it not duplicate any valid real argument.

The various flagged vector constructs are the safest ways to handle vectoring during recursion. There is little to chose among them, except that the ones using a variable target argument are more versatile in that they allow deeper recursion.

I said above that the virtual command approach is deep magic - it is also somewhat limited in that it cannot be used in batch files that require real arguments. Where it can be used, it allows not only recursion, but also determination of at least a couple of command lines in a batch file at execution time:


 @echo off
 %1 %2
 %3 %4
 :end
is a trivial example - the batch file consists of any one or two two word commands, but which ones they are isn't determined until the program is run. If run with no arguments, it does nothing. If invoked (assuming it is named FOO.BAT)

 foo dir *.* del *.bat
it would perform a DIR *.* on the current directory and then delete all the batch files, including itself, from the default directory. This isn't really useful, but it illustrates the concept that the same syntax that is used to control recursion vectoring can also be used for other purposes - even in the same batch file:

 @echo off
 %1 %2 %3
 if exist %0.txt call $0 goto pass2 
 :goto end
 :pass2
 dir %0.*
 :end
Assuming that the program is named FOO.BAT and that FOO.TXT does not exist, if it is invoked with the arguments

 foo copy foo.bat foo.txt
its behavior would be rather different from when it was invoked with no arguments, and the exact same syntax (%1 %2 %3) would have had actions of totally different natures on the two passes (first case only), and would never act as vectoring code at all in the second case. This virtual command concept is so new that I really haven't had time to explore its implications.

  ** Copyright 1995, Ted Davis - all rights reserved ** 

Input and feedback from readers are welcome. NOTE: the subject of the message must contain the word "batch" for the message to get past the spam filter.

Back to the Table of Contents page

Back to my personal links page - back to my home page