1

I'm a complete noob when it comes to anything Windows related, so I'm hoping this is an easy question for someone. I'm using Win7 if it makes a difference.

I have the following code in a .cmd file which I run twice in a row from the command line which produces the following output:

set /p input_tmp=input something: || set input_tmp=default
echo "input_tmp outside if: %input_tmp%"
if "%input_tmp%"=="default" (
    echo "input_tmp inside if: %input_tmp%"
)

-------------output 1---------------
input something: cat
"input_tmp outside if: cat"
-------------output 2---------------
input something: dog
"input_tmp outside if: dog"

However, when I run the following code...

if not "%~1"=="something" (
        set /p input_tmp=input something: || set input_tmp=default
        echo "input_tmp outside if: %input_tmp%"
        if "%input_tmp%"=="default" (
            echo "input_tmp inside if: %input_tmp%"
        )
)

-------------output 1---------------
input something: cat
-------------output 2---------------
input something: dog
"input_tmp outside if: cat"

Being a Java programmer for Linux ...this confuses the begezus out of me.

codenoodle
  • 982
  • 6
  • 19

1 Answers1

2

In batch files, when a block of code (the code inside parenthesis) is reached, all the block is parsed and all variable reads are replaced with the value stored in the variable before starting to execute the code. If the code in the block changes the value in the variable, this value can not be retrieved from inside the same block, as the read operation does not exist, it was replaced with the value in the variable.

To avoid this, delayed expansion must/should be used. This allows to change, where necessary, the syntax %var% to !var!, indicating to the parser that the read operation on the variable must be delayed until the command is executed.

setlocal enabledelayedexpansion

if not "%~1"=="something" (
        set /p input_tmp=input something: || set input_tmp=default
        echo "input_tmp outside if: !input_tmp!"
        if "!input_tmp!"=="default" (
            echo "input_tmp inside if: !input_tmp!"
        )
)
MC ND
  • 69,615
  • 8
  • 84
  • 126
  • This does it! Thanks so much for the quick response! Side question ...why does it do this? – codenoodle Sep 16 '14 at 16:47
  • @gr33ngapion, just my opinion, but... the batch parser removes the variable reads with its value so this value can be part of the command, not only data retrieved to be processed by the command (ex. `set "myCmd=dir"` , `%myCmd% /b`). The variable/value replacement is obvious over one line, but as blocks are readed and parsed as if only a line is being read (more or less), you end with this behaviour. – MC ND Sep 16 '14 at 17:05
  • Hmmm... I feel like that's not actually too hard to work around without this "feature." Oh well. Just something else I have to remember I guess. Thanks for clarifying! – codenoodle Sep 16 '14 at 17:55
  • Is this parenthesis behavior of batch files exist inside functions or labels as well? I mean if a label or a function has if code or for code or anything with parenthesis, then also will the same behavior (substitute variables during parse time) be valid of the batch ? – AskQuestionsP Dec 21 '21 at 08:58