SiegeX
SiegeX

Reputation: 140237

How to recursively expand an environment variable?

Assume the following:

echo %MY_ENV_VAR% expands to %USERPROFILE%\some\path
echo %USERPROFILE% expands to C:\Users\MyUser

My goal is to create an empty file at the following path: C:\Users\MyUser\some\path\FOO.txt.

I tried the following command: type nul > %MY_ENV_VAR%\FOO.txt

Unfortunately the output is an error which states The system cannot find the path specified.

I'm pretty certain this is because the shell is not recursively expanding %MY_ENV_VAR% and it's trying to find a literal path that begins with %USERPROFILE%.

How can I best accomplish my goal?

Upvotes: 2

Views: 1497

Answers (1)

MC ND
MC ND

Reputation: 70923

rem Create the problem
set "MY_ENV_VAR=%%USERPROFILE%%\some\path"
echo %MY_ENV_VAR%

rem One solution
call set "MY_ENV_VAR=%MY_ENV_VAR%"
echo %MY_ENV_VAR%

In the call line, the parser will replace %MY_ENV_VAR% with the content of the variable, generating

call set "MY_ENV_VAR=%USERPROFILE%\some\path"

When this command is executed, the call will force a second parse phase, generating

set "MY_ENV_VAR=C:\Users\MyUser\some\path"

Of course, if USERPROFILE contains another variable reference, the process must be repeated.

edited - Added a "solution" to the "recursive" problem and placed all the code inside a subroutine.

@echo off
    setlocal enableextensions disabledelayedexpansion

    rem Create the problem
    set "_1first=c:\users"
    set "_2second=%%_1first%%\test"
    set "_3third=%%_2second%%\so & me\path"
    set "_4fourth=%%_3third%%"

    set "MY_ENV_VAR=%%_4fourth%%"

    echo inner variables
    echo -----------------------------
    set _
    echo -----------------------------
    echo(

    echo "MY_ENV_VAR = [%MY_ENV_VAR%]"
    call :expandInnerVariables MY_ENV_VAR
    echo "MY_ENV_VAR = [%MY_ENV_VAR%]"
    goto :eof

:expandInnerVariables varName
    setlocal enableextensions disabledelayedexpansion
    set "aux=="
    for /l %%i in (0 1 100) do (
        setlocal enabledelayedexpansion
        if "!%~1!"=="" (
            endlocal & goto :endExpand
        ) else for /f "delims=" %%a in ("=!%~1!") do (
            endlocal & call set "%~1%%a"
            setlocal enabledelayedexpansion 
            for /f "delims=" %%b in ("=!%~1!") do (
                endlocal & set "aux=%%b" & if %%a==%%b goto :endExpand
            )
        )
    )
    :endExpand
    endlocal & set "%~1%aux%"
    goto :eof

Upvotes: 3

Related Questions