9

Consider this example, where I start a new "sub" instance of cmd.exe, and then try to set a new environment variable in it, and then check if it has the proper value set (this is in cmd.exe of Windows 10):

>cmd /c "SET OPERATION=NEW & SET O"
OneDrive=C:\Users\user\OneDrive
OPERATION=NEW
OS=Windows_NT

So, as noted in https://superuser.com/a/776506/688965 - by doing SET O I would "display all variables that begin with the letter 'O'", and indeed, it shows that an environment variable OPERATION exists, and its value is NEW. So far, so good.

However, if I try to print the environment value instead, it does not expand:

>cmd /c "SET OPERATION=NEW & echo %OPERATION%"
%OPERATION%

... however, if I try to expand any other environment variable, it works ?!:

>cmd /c "SET OPERATION=NEW & echo %OS%"
Windows_NT

Why does this happen? How can I set an environment variable, and then print it with echo in a single line, in a cmd.exe subshell?

2

2 Answers 2

5

Why does this happen?

The %OPERATION% is expanded (Phase 1) before the variable has been set (Phase 7).

See How does the Windows Command Interpreter (CMD.EXE) parse scripts? for the gory details:

Processing a line of code in a batch file involves multiple phases.

Here is a brief overview of the various phases:

Phase 0) Read Line:

Phase 1) Percent Expansion:

Phase 1.5) Remove : Remove all Carriage Return (0x0D) characters

Phase 2) Process special characters, tokenize, and build a cached command block: This is a complex process that is affected by things such as quotes, special characters, token delimiters, and caret escapes.

Phase 3) Echo the parsed command(s) Only if the command block did not begin with @, and ECHO was ON at the start of the preceding step.

Phase 4) FOR %X variable expansion: Only if a FOR command is active and the commands after DO are being processed.

Phase 5) Delayed Expansion: Only if delayed expansion is enabled

Phase 5.3) Pipe processing: Only if commands are on either side of a pipe

Phase 5.5) Execute Redirection:

Phase 6) CALL processing/Caret doubling: Only if the command token is CALL

Phase 7) Execute: The command is executed

7

How can I set an environment variable, and then print it with echo in a single line, in a cmd.exe subshell?

To enable neccessary delayed expansion in a cmd subshell you'll have to use the /V:ON switch of cmd.exe and use an ! exclamation mark instead of the % percent sign.

> cmd /V:ON /C "SET OPERATION=NEW&echo [!OPERATION!]"
[NEW]

Just a reminder
The trailing space in your original set will be part of the variable content:

> cmd /V:ON /C "SET OPERATION=NEW &echo [!OPERATION!]"
[NEW ]

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .