Take the 2-minute tour ×
Server Fault is a question and answer site for professional system and network administrators. It's 100% free, no registration required.

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"?

Thanks!

share|improve this question
    
You've got "BBB" where I think you mean "ZZZ" and "dir1" where you might mean "dirA". –  Dennis Williamson Aug 31 '09 at 16:38
    
Yes thanks you! I fixed it! –  raoulsson Aug 31 '09 at 16:59

2 Answers 2

up vote 1 down vote accepted

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:

setlocal ENABLEDELAYEDEXPANSION

More info here.

share|improve this answer
    
Good to know! Thanks! –  raoulsson Aug 31 '09 at 13:00

I might have handled it a little simpler...

@ECHO OFF       
SET SOURCE_DIR=
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.

share|improve this answer
    
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. –  Nathan Hartley Sep 3 '09 at 20:17

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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