1

I have been translating some shell code to MS-DOS Batch. In my code, I have the sample:

for %%i in (%*) do set "clargs=!clargs! %%i"

If I input the argument "-?" (without the quotation marks), it is not added to clargs. I assume it is because '?' is a wildcard character. Is there anything I can do to ensure that for does not do special things because of the question mark being located in the argument?

Sammidysam
  • 43
  • 1
  • 7

2 Answers2

2

You are correct, the wild card characters * and ? are always expanded when used within a FOR IN() clause. Unfortunately, there is no way to prevent the wildcard expansion.

You cannot use a FOR loop to access all parameters if they contain wildcards. Instead, you should use a GOTO loop, along with the SHIFT command.

set clargs=%1
:parmLoop
if "%~1" neq "" (
  set clargs=%clargs% %1
  shift /1
  goto :parmLoop
)

Although your sample is quite silly, since the resultant clargs variable ends up containing the same set of values that were already in %*. If you simply want to set a variable containing all values, simply use set clargs=%*

More typically, an "array" of argument variables is created.

set argCnt=0
:parmLoop
if "%~1" equ "" goto :parmsDone
set /a argCnt+=1
set arg%argCnt%=%1
shift /1
goto :parmLoop
:parmsDone

:: Working with the "array" of arguments is best done with delayed expansion
setlocal enableDelayedExpansion
for /l %%N in (1 1 %argCnt%) do echo arg%%N = !arg%%N!

See Windows Bat file optional argument parsing for a robust method to process unix style arguments passed to a Windows batch script.

Community
  • 1
  • 1
dbenham
  • 127,446
  • 28
  • 251
  • 390
  • I agree it was very silly--I was thinking of replacing it with a better sample but it was the best line to display what I meant. The actual code sample is about 20 lines long now which I didn't feel was necessary to show what I meant. I will try out this sample tomorrow and if it works I will mark your answer as correct. Thanks! – Sammidysam May 27 '13 at 04:08
  • So I have http://pastebin.com/bDABiTy6 and it works, but how would I loop through the values of args in a similar manner, as args could contain "-?" and then the for loop interpreting args would ignore it. – Sammidysam May 30 '13 at 13:55
  • @Sammidysam - Huh? What FOR loop are you referring to? There isn't any FOR loop in my answer, nor is there a FOR loop in your pastebin code. – dbenham May 30 '13 at 14:24
  • Oh, sorry. I meant http://pastebin.com/GfMkub1X which is my for loop to take the arguments put into the program and interpret them. The program initially splits up the command line arguments into arguments for gcc/g++ and arguments for the program calling gcc/g++. – Sammidysam May 30 '13 at 15:30
  • Do I need to just interpret the arguments for the program in the loop separating libraries for gcc/g++ and arguments for the program? – Sammidysam May 31 '13 at 14:01
  • @Sammidysam - Presumably you are doing something like `set args=%*`. Don't do that :-) Use the loop construct in this answer, but don't store all the arguments in one variable. Instead, set a new variable for each argument found. – dbenham May 31 '13 at 14:26
  • The second code comes after the first. Sorry for not clarifying that. So you mean that I make a variable that stores whether each argument has come up, and then instead of looping through the list of arguments for the program I just check what arguments are there (by checking if the variable for the argument being present represents true)? – Sammidysam May 31 '13 at 15:42
  • @Sammidysam - Something like that. Have a look at my updated answer. – dbenham May 31 '13 at 16:00
  • In your second sample, the first argument is skipped. Adding a simple firstTime variable fixes it though. Thank you VERY much! The code works great! – Sammidysam May 31 '13 at 19:33
  • @Sammidysam - You are correct, I had the SHIFT in the wrong location. I fixed the code in the answer. – dbenham May 31 '13 at 19:52
0
@ECHO OFF
SETLOCAL
SET dummy=%*
FOR /f "tokens=1*delims==" %%f IN ('set dummy') DO CALL :addme %%g
ECHO %clargs%
GOTO :eof

:addme
IF "%~1"=="" GOTO :EOF 
IF DEFINED clargs SET clargs=%clargs% %1
IF NOT DEFINED clargs SET clargs=%1
SHIFT
GOTO addme

I severly doubt you'll get a completely bullet-proof solution. The above solution will drop separators (comma, semicolon, equals) for instance. Other solutions may have problems with close-parentheses; there's the perpetual % and ^ problems - but it will handle -?

But for your purposes, from what you've shown, what's wrong with

set clargs=%clargs% %*

(No doubt you'll want to process further, but ve haff vays...)

Magoo
  • 77,302
  • 8
  • 62
  • 84