How to Use a Variable's Value as Another Variable Name (Indirect Expansion)
In advanced batch scripting, you may encounter a situation where you need to use the value of one variable as the name of another. This is known as indirect expansion or a "double variable" lookup. For example, you might have a variable CurrentCheck that holds the string "ServerName", and you need to get the value of the actual %ServerName% variable.
This is a powerful but non-obvious technique. Windows Batch does not have a direct syntax for this (like %%MyVar%%), so we must use a specific workaround. This guide will teach you the definitive "pure-batch" method using the CALL SET trick and explain why it works, a crucial skill for creating dynamic and flexible scripts.
The Challenge: No Direct Nested Expansion
The fundamental problem is that the cmd.exe parser expands variables in a single pass. If you have a variable that contains the name of another variable, a simple ECHO will not work.
@ECHO OFF
SET "TargetVarName=Color"
SET "Color=Red"
ECHO The target variable name is: %TargetVarName%
ECHO The desired value is the content of the 'Color' variable.
REM --- These attempts will FAIL ---
ECHO Attempt 1: %TargetVarName%
ECHO Attempt 2: %%TargetVarName%%
Output:
The target variable name is: Color
The desired value is the content of the 'Color' variable.
Attempt 1: Color
Attempt 2: %Color%
The first attempt just gives us the value of TargetVarName. The second attempt just wraps the value in percent signs. Neither gives us "Red".
The Core Method: The CALL SET Trick
The standard and most reliable way to force a second round of expansion is to use the CALL command, typically with SET. The CALL command causes the line to be parsed twice.
Syntax: CALL SET "Result=%%%TargetVarName%%%"
CALL: This forces a second pass over the command.SET "Result=...": The command we want to run.%%%TargetVarName%%%: This is the magic syntax. It uses three percent signs on each side.
How to Use It with Delayed Expansion
In modern scripts, this technique is most often used inside loops where DelayedExpansion is enabled. The syntax changes slightly, but the principle is the same.
Syntax with Delayed Expansion: CALL SET "Result=%%!TargetVarName!%%"
Here, !TargetVarName! is expanded first (during the initial parse), and then the CALL command processes the result. This is the most common and useful form of the command.
Basic Example: A Dynamic Lookup
This script dynamically builds a variable name and then uses the CALL SET trick to retrieve its value.
@ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
REM --- Define our "database" of variables ---
SET "Animal=Cat"
SET "Cat_Sound=Meow"
SET "Dog_Sound=Woof"
ECHO The chosen animal is: !Animal!
ECHO We want to find the sound for this animal.
ECHO.
REM --- Dynamically construct the name of the variable we want to look up ---
SET "SoundVarName=!Animal!_Sound"
ECHO The variable we need to look up is named: !SoundVarName!
REM --- Use the CALL SET trick to perform the indirect expansion ---
CALL SET "FinalSound=%%!SoundVarName!%%"
ECHO.
ECHO The final result is: !FinalSound!
ENDLOCAL
Output:
The chosen animal is: Cat
The variable we need to look up is named: Cat_Sound
The final result is: Meow
How the CALL SET Trick Works (The Two-Pass Parse)
The command CALL SET "FinalSound=%%!SoundVarName!%%" is the key. Here's a step-by-step breakdown of how the parser processes it:
-
First Pass (Initial Parse):
- The command processor scans the line before execution.
- Because delayed expansion is on, it sees
!SoundVarName!and immediately replaces it with its value, which isCat_Sound. - The command is now transformed into:
CALL SET "FinalSound=%%Cat_Sound%%"
-
Second Pass (Forced by
CALL):- The
CALLcommand takes the transformed line and tells the processor to parse it again. - On this second pass, the parser sees
%%Cat_Sound%%. - The batch parser resolves pairs of percent signs (
%%) into a single, literal percent sign (%). So,%%Cat_Sound%%becomes%Cat_Sound%. - Now, the parser sees
%Cat_Sound%which is a standard variable. It expands this to its value,Meow. - The final command that is actually executed is:
SET "FinalSound=Meow"
- The
This two-step parsing process is what allows for the powerful indirect expansion.
Common Pitfalls and How to Solve Them
Problem: Forgetting the CALL Command
If you forget CALL and just use SET, the second pass of parsing never happens.
Example of a script with error:
SET "FinalSound=%%!SoundVarName!%%"
ECHO !FinalSound!
Output:
%Cat_Sound%
The variable is literally set to the string %Cat_Sound% because the second expansion was never triggered.
Problem: Getting the Percent Signs Wrong
The number of percent signs is precise and crucial.
- With Delayed Expansion (
!VarName!): You need two percent signs on each side:%%!VarName!%%. - With Standard Expansion (
%VarName%): You need three percent signs on each side:%%%VarName%%%.
Solution: For almost all advanced scripts that require this technique, you will be using delayed expansion. Memorize the CALL SET "Result=%%!VarName!%%" pattern.
Practical Example: A Reusable "GetValueByName" Subroutine
This is a professional and highly reusable way to implement this logic. This subroutine takes a variable name as input and returns its value.
@ECHO OFF
SETLOCAL
SET "MyTestVariable=This is a secret message."
ECHO --- Getting a variable's value dynamically ---
CALL :GetValueByName "MyTestVariable" TheValue
ECHO The value is: %TheValue%
GOTO :EOF
:GetValueByName
REM Subroutine to get the value of a variable whose name is passed in.
REM %1: The NAME of the variable to look up.
REM %2: The NAME of the variable to store the result in.
SETLOCAL ENABLEDELAYEDEXPANSION
SET "LookupName=%~1"
CALL SET "Result=%%!LookupName!%%"
(
ENDLOCAL
SET "%2=%Result%"
)
GOTO :EOF
Conclusion
Indirect variable expansion is an advanced but essential technique for writing dynamic and flexible batch scripts, especially for creating pseudo-arrays or performing lookups.
Key takeaways:
- Batch has no direct syntax for nested expansion.
- The
CALL SETcommand is the standard method used to force a second pass of parsing, which makes indirect expansion possible. - When using delayed expansion, the correct syntax is
CALL SET "Result=%%!VarName!%%". - This technique is perfect for creating dynamic lookups, working with pseudo-arrays, or building reusable subroutines.