How-to: Create Batch file macros

A macro allows you to embed blocks of code in a variable. Like calling a subroutine or function this allows reusing the same block of code multiple times, the difference is that by placing the code in a variable the performance will be much faster.

This is an advanced technique but can be very useful in scripts that include large blocks of code or looping commands where the performance of other methods is too slow.

A macro which runs exit /b

set _ex=exit /b

You can then exit a subroutine with:

%_ex%

A macro which lists all the .CSV files in a folder:

Set _macro=Dir c:\demo\*.csv

We can now run the Macro like this:

%_macro%

So far so like the DOSKEY command, but to make this more powerful you will want to pass arguments to the macro, in the example above you might want to pass the name of the folder/file to be listed.

We can use a placeholder character, (in this case #) and then use variable String Substitution to swap that out at runtime:

SET _macroDir=Dir # /s

We can now run the Macro to get a file listing including subdirectories like this:

%_macroDir:#=c:\demo\*.csv%
%_macroDir:#=c:\work\*.txt%
Another example which counts numbers:
SET "_macroCount=FOR /L %%G in (1, 1, #) DO (Echo %%G)"  

Calling that macro and passing 3

%_macroCount:#=3%  

Will output:

1
2
3

Passing multiple arguments to a macro is a little more complex, the method discovered by Jeb, is to place a For /L command within the macro, set to run 2 steps each time the macro is run:

The basic structure of the macro definition:

Set _macro=For /l %%n in (1 1 2) do if %%n==2 (Echo Main MACRO goes here.) else setlocal enableDelayedExpansion ^& Set argv=, 

%_macro% arg1 arg2

 :: The macro will expand to:
 :: for /l %%n in (1 1 2) do if %%n==2 (Echo Main MACRO goes here.) else setlocal enableDelayedExpansion & Set argv=, arg1 arg2

 :: which is equivalent to:
 ::    setlocal enableDelayedExpansion
 ::    Set argv= arg1 arg2
 ::    Echo Main MACRO goes here.

Examples:

@echo off
cls
setlocal DisableDelayedExpansion
set LF=^


::Above 2 blank lines are required - do not remove
set ^"\n=^^^%LF%%LF%^%LF%%LF%^^"

set _macrodemo=for /L %%n in (1 1 2) do if %%n==2 (%\n%
      for /F "tokens=1 delims=, " %%G in ("!argv!") do (%\n%
         echo _argument1=%%G %\n%
         set "_argument1=!%%~G!"%\n%
         dir !_argument1!\*.xls%\n%
      ) %\n%
) ELSE setlocal enableDelayedExpansion ^& set argv=,

set "_testfolder=c:\demo"
%_macrodemo% _testfolder

In a macro where more than one argument need to be passed, these will become tokens 2,3,4... in the FOR / F command.

A library of macros can be defined by running a single MACROS.CMD batch file, allowing the library macros to be used in multiple batch files.

Credits: Ed Dyreen, Jeb and Dave Benham, the original dostips forum threads are here (basic concepts) and here (macros with parameters).

“Macro dictionary definition: 1. Large 2. Long 3. Inclusiveā€¯ ~ from the Greek 'makros'

Related commands

How-to: functions - How to package blocks of code.
CALL - Call one batch program/subroutine from another.
How the %LF% newline variable hack works - StackOverflow.
DOSKEY - Edit command line, recall commands, and create macros.


 
Copyright © 1999-2024 SS64.com
Some rights reserved