I want to set a variable e.g. %p%
and then use it in the same line in CMD.
e.g.:
set p=notepad.exe&%p%
This not works. But %p%
is set for the next line. Therefore if I execute this line for second time, it works.
How can I use %p%
in the same line?
To set (or change) a environment variable, use command " set varname=value ". There shall be no spaces before and after the '=' sign. To unset an environment variable, use " set varname= ", i.e., set it to an empty string.
To pass variable values via the command line, use the PrjVar ( pv ) or PSVar ( psv ) arguments for the project and project suite variables respectively. Variable values you pass via the command line are temporary.
Use double percent signs ( %% ) to carry out the for command within a batch file. Variables are case sensitive, and they must be represented with an alphabetical value such as %a, %b, or %c. ( <set> ) Required. Specifies one or more files, directories, or text strings, or a range of values on which to run the command.
When you execute a batch file, each line or block of lines (lines enclosed in parenthesis) is first parsed and then executed. During the parse, the read operations on the variables are replaced with the value inside the variable before the commands are executed. So if in a line/block a variable value is changed, you can not retrieve this changed value as the parser has removed the read operation with the value in the variable before the change has been made.
So, your code
set p=notepad.exe&%p%
is parsed and converted to
set p=notepad.exe&
where the read operation to get %p%
has been replaced with the value in the variable (the sample assumes the variable is empty). Then this parsed line is executed.
Why does it work the second time? Because in the previous run the variable has been set and, if it has not been reset, when the parser do the replacement in the second run the variable contains a value to replace in the line.
To see that this is a parse before execute behaviour, you can change your line to
set p=notepad.exe&set p
that is, set the variable and dump the environment content (variables starting with p) and you will see that the variable has been set to notepad.exe
. As this line does not contain any read operation on the variable everything works as expected.
How to solve your problem? There are some options
Delayed expansion
When delayed expansion is enabled, the syntax on variable reads can be changed, where needed, from %var%
to !var!
, indicating to the parser that the substitution on the read operation needs to be delayed until the command execution
setlocal enabledelayedexpansion
set p=notepad.exe&!p!
This same behaviour can be enabled if the command processor is called with /v:on
cmd /v:on /c "set p=notepad.exe&!p!"
Force a second parse on the command
This uses the call
command to force a second parse on the line
set p=notepad.exe&call %%p%%
The first default parse replaces the literal %%p%%
with the literal %p%
(%%
is a escaped percent sign) without doing any variable replacement, and when the call
command is executed, the line is parsed again, so the literal %p%
is interpreted as a variable read and is replaced with the value in the variable
What to use? It depends. Delayed expansion solution has better execution times that call
solution (call
command does a lot more work), but when delayed expansion is enabled exclamation characters (!
) contained in the data become a problem that needs to be properly handled.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With