10

I'm trying to loop through the arguments that I am passing to a batch file. Based on the argument, I want to set a variable flag true or false for use later in the script

So my command is "myscript.bat /u /p /s"

And my code is:

FOR /f %%a IN ("%*") DO (
  IF /I "%%a"=="/u" SET UPDATE=Y
  IF /I "%%a"=="/p" SET PRIMARY=Y
  IF /I "%%a"=="/s" SET SECONDARY=Y
)

It only works if i have a single argument, which tells me that it is getting the entire list of arguments as a single argument. I've tried "delims= " but to no avail. Any thoughts on getting each spaced argument?


What about adding a value to one of the params?

myscript.bat /u /p /d TEST /s

:loop
IF "%~1"=="" GOTO cont
IF /I "%~1"=="/u" SET UPDATE=Y
IF /I "%~1"=="/p" SET PRIMARY=Y
IF /I "%~1"=="/s" SET SECONDARY=Y
IF /I "%~1"=="/d" SHIFT & SET DISTRO="%~1"
SHIFT & GOTO loop

:cont

But the SHIFT that comes inline with the last IF doesn't actually shift anything. DISTRO ends up being "/d" instead of "TEST"

casperOne
  • 73,706
  • 19
  • 184
  • 253
DssTrainer
  • 1,439
  • 3
  • 12
  • 15

2 Answers2

24

You're not too far off on your original piece, and since I dislike GOTO loops, I thought I'd post this:

FOR %%a IN (%*) DO (
  IF /I "%%a"=="/u" SET UPDATE=Y
  IF /I "%%a"=="/p" SET PRIMARY=Y
  IF /I "%%a"=="/s" SET SECONDARY=Y
)

The reason it was only working with one parameter is the over-use of quotes. By putting %* in quotes you were making the entire commandline one single token. also, the /F variant of FOR isn't what you were looking for either. The documentation available from FOR /? should help clear things up.

MarbleMunkey
  • 741
  • 5
  • 5
6

You could loop over the arguments using SHIFT, GOTO and an extra IF to check if there are no more parameters to parse:

:loop
IF "%~1"=="" GOTO cont
IF /I "%~1"=="/u" SET UPDATE=Y
IF /I "%~1"=="/p" SET PRIMARY=Y
IF /I "%~1"=="/s" SET SECONDARY=Y
SHIFT & GOTO loop

:cont
...

UPDATE (addressing the case when a parameter has an argument of its own)

The SHIFT in the IF statement that checks for /d does work. The issue is that the entire line is evaluated at once and both instances of %~1 get replaced with the same value, which is /d at that point.

So, basically the solution in this case would be to cause the interpreter to evaluate the SET DISTRO="%~1" part separately from the IF /I "%~1"=="/d". There can be various approaches to this. For instance, you could simply move SHIFT & SET DISTRO="%~1" to the next line and skip it if %~1 is not /d:

...
IF /I NOT "%~1"=="/d" GOTO skip_d
SHIFT & SET "DISTRO=%~1"
:skip_d
...

Another method could be to assign a special value (e.g. a ?) to DISTRO and shift when /d is encountered. Then, on the next line, check if DISTRO has that special value and set it to %~1:

...
IF /I "%~1"=="/d" SHIFT & SET DISTRO=?
IF "%DISTRO%"=="?" SET "DISTRO=%~1"
...
Andriy M
  • 76,112
  • 17
  • 94
  • 154