Skip to main content

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%
note

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:

  1. 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 is Cat_Sound.
    • The command is now transformed into: CALL SET "FinalSound=%%Cat_Sound%%"
  2. Second Pass (Forced by CALL):

    • The CALL command 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"

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%
note

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 SET command 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.