How does batch Echo parse variables in text

You need to actually call env.bat at some point so that the variables get set. Also, because echo !key!=!value! by itself will display dev_env=%a%, etc. you need to use call for a second pass of variable expansion.

@echo off
setlocal enabledelayedexpansion

call env.bat
for /f "skip=1 eol=: tokens=2,3 delims== " %%i in (.\env.bat) do (
    set key=%%i
    set value=%%j

    call echo !key!=!value! >>.\custom_variable.properties
)

Ok. Three points here:

  • First of all, the lines in the env.bat file will not be executed inside the env.bat file itself, but in a posterior execution in the copy_env.bat file, right? For this reason, the values of a and b can not be taken via an "immediate" %a% and %b% expansion, but via a "delayed" !a! and !b! one instead.

  • In second place, in copy_env.bat you have the setlocal enabledelayedexpansion and endlocal commands inside the for /F loop. This means that every value that is set in a for iteration will be lost when such an iteration ends. In order to preserve the values for the next for /F cycles, the setlocal-endlocal commands must be moved outside the for /F loop.

  • Finally, you have this command: echo !key!=!value! that just display a line like a=123, but you have not a command with the real assignment of such a value. It is necessary to add the equivalent set !key!=!value! command in order to store such values for the posterior assignments.

The final working programs are these ones:

env.bat:

@echo off
set a=123
set b = 456

set dev_env=!a!
set prod_env=!b!

copy_env.bat:

@echo off
setlocal enabledelayedexpansion
for /f "skip=1 eol=: tokens=2,3 delims== " %%i in (.\env.bat) do (
    set key=%%i
    set value=%%j

    set !key!=!value!
    echo !key!=!value! >> .\custom_variable.properties

)
endlocal