I need to set some variables based on an argument for a windows batch script.

@echo off       
if [%1]==[] (
    echo "Usage: xxx <AAA|ZZZ>"
) else (
    if [%1]==[AAA] (
        SET SOURCE_DIR=c:\dirA
    ) else if [%1]==[ZZZ] (
        SET SOURCE_DIR=c:\dirZ
    echo Source dir is: %SOURCE_DIR%

When I call the above script with parameter AAA, I get the output

Source dir is: c:\dirA

after the second call. From then onwards when I alternate between AAA and ZZZ, I get this pattern:

C:\stageing-area>test.bat AAA
Source dir is: c:\dirZ
C:\stageing-area>test.bat ZZZ
Source dir is: c:\dirA
C:\stageing-area>test.bat AAA
Source dir is: c:\dirZ
C:\stageing-area>test.bat ZZZ
Source dir is: c:\dirA

So it looks like I am manipulating a global variable that is available even after the script has finished. This alone doesn't bother me but that the new setting is only available after the script terminates is a problem, as the rest of my script depends on it (obviously).

What is the correct use of local variables in this context? How to explain the weird behaviour of the above "defered state setting"?


  • You've got "BBB" where I think you mean "ZZZ" and "dir1" where you might mean "dirA". Aug 31 '09 at 16:38

Variables in a batch file are by default expanded at the beginning of script execution; you need to use delayed expansion, which is available with the "!" delimiter:

echo Source dir is: !SOURCE_DIR!

This only works if delayed expansion is enabled for the command interpreter, which by default is not; so you need to enable it when starting the interpreter, using CMD.EXE /V.

You can also enable it using this statement in your batch file:


More info here.


I might have handled it a little simpler...

@ECHO OFF       
IF /I [%1]==[AAA] SET SOURCE_DIR=c:\dirA
IF /I [%1]==[ZZZ] SET SOURCE_DIR=c:\dirZ
IF [%SOURCE_DIR]==[] (
    ECHO "Usage: xxx <AAA|ZZZ>"
    EXIT 1
ECHO Source dir is: %SOURCE_DIR%

I have to admit, I am a bit baffled as to why this works when the example in the question does not. My best guess is that it is a scoping problem. Because in the example, the variable SOURCE_DIR was set within the parens, its value in the root scope it remains unchanged. My script changes SOURCE_DIR in the root scope.

As to why the Delayed Expansion trick causes it to pickup the change that was made a scope level deeper, it seems the expansion happens at the beginning of each scope change. So by delaying, you are basically forcing it to re-expand after returning to the root scope.

  • This works but I cannot see what the difference to my version is? There must me one but I'm not getting it... Could you explain please?
    – raoulsson
    Aug 31 '09 at 16:57
  • Not sure what I was thinking. I see the problem clearly now. Sep 3 '09 at 20:17

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.