48

I have a batch-script with multiple arguments. I am reading the total count of them and then run a for loop like this:

@echo off
setlocal enabledelayedexpansion

set argCount=0
for %%x in (%*) do set /A argCount+=1
echo Number of processed arguments: %argCount%

set /a counter=0
for /l %%x in (1, 1, %argCount%) do (
set /a counter=!counter!+1 )

What I want to do now, is to use my running variable (x or counter) to access the input arguments. I am thinking aobut something like this:

REM Access to %1 
echo %(!counter!)

In an ideal world this line should print out my first command line argument but obviously it doesn't. I know I am doing something wrong with the % operator, but is there anyway I could access my arguments like this?

//edit: Just to make things clear - the problem is that %(!counter!) provides me with the value of the variable counter. Meaning for counter=2 it gives me 2 and not the content of %2.

4
  • if the arguments are more than 9 you can't access all of them without shift Commented Nov 7, 2013 at 12:29
  • This is another issue I might encounter, but let's just assume that I will have less than 10 arguments Commented Nov 7, 2013 at 12:30
  • 5
    Also, for %%x in (%*) do ... will not give the desired result if any parameter contains * or ? character. I always use a GOTO loop with SHIFT if I want to load the parameters into an array of variables. Commented Nov 7, 2013 at 16:08
  • If one of the arguments contains a wildcard character, e.g. "file*.txt" then it is not processed. Any idea how to fix? Commented Mar 1, 2023 at 10:09

6 Answers 6

80
@echo off
setlocal enabledelayedexpansion

set argCount=0
for %%x in (%*) do (
   set /A argCount+=1
   set "argVec[!argCount!]=%%~x"
)

echo Number of processed arguments: %argCount%

for /L %%i in (1,1,%argCount%) do echo %%i- "!argVec[%%i]!"

For example:

C:> test One "This is | the & second one" Third
Number of processed arguments: 3
1- "One"
2- "This is | the & second one"
3- "Third"

Another one:

C:> test One Two Three Four Five Six Seven Eight Nine Ten Eleven Twelve etc...
Number of processed arguments: 13
1- "One"
2- "Two"
3- "Three"
4- "Four"
5- "Five"
6- "Six"
7- "Seven"
8- "Eight"
9- "Nine"
10- "Ten"
11- "Eleven"
12- "Twelve"
13- "etc..."
Sign up to request clarification or add additional context in comments.

7 Comments

Tthis one is working as is, for me, unlike current solution from @npocmaka (windows 10 familly)
A little more context on how the whole thing works would be nice, but the solutions does what it says on the thin, I give you that. :-)
This has trouble when the argument has some format, e.g. this link: https://www.tagesschau.de/investigativ/ndr-wdr/spaeh-software-pegasus-projekt-101.html. I can't name the exact problem, but it doesn't even count this argument. It probably also has problems if one of the argument contains *.
Be aware that this needs the delayed expansion (setlocal enableDelayedExpansion), which my preferred answer doesn't.
This answer splits on semicolons. Calling with "One;Two" will output two lines "One" and "Two".
|
39
:loop
@echo %1
shift
if not "%~1"=="" goto loop

7 Comments

Where are the better answers? I like this one because it is super succinct, minimal, and straightforward.
What I think @jeb is trying to say is that you should provide an explanation for your answer. I think it's great, but with details on what each command does, and maybe a usage example, you'll get more upvotes :)
This answer works when the arguments contain special characters like * but iterates one time too many when there are no arguments.
Very helpful information @Arnaud, thank you for explaining the issue and shedding light on this!
This breaks when an empty argument "" is in the mix, skipping anything after. Also, I can't get this version to preserve equals signs :(
|
14

here's one way to access the second (e.g.) argument (this can be put in a for /l loop, see below.):

@echo off
setlocal enableDelayedExpansion
set /a counter=2
call echo %%!counter!
endlocal

so:

setlocal enableDelayedExpansion
set /a counter=0
for /l %%x in (1, 1, %argCount%) do (
 set /a counter=!counter!+1
 call echo %%!counter! 
)
endlocal

10 Comments

Ok I need to ask, even if it may obvious and I am just having a blackout: Is there any way how I can get that value into a variable now? Now that I have read the Input paramaeters I want to compare them with some strings. And I am not quite sure how I can access that string now...?
with call set "_var=%%!counter!".you need a temp variable because if cannot be called
and then you can compare with if -> if "!_var!" equ "something" echo this is something
Are you sure that I have to put the " around the whole set call?
it is a safe strategy. this allows you to include special characters in the value like |&><.... and will ensure you that there is no extra space at the end (which in some cases could break your logic)
|
12

If to keep the code short rather than wise, then

for %%x in (%*) do (
   echo Hey %%~x 
)

3 Comments

Is this approach unwise? And if so, why?
@isapir This approach will fail if one of the argument contains * as I just learned the hard way.
this one is more understandable than @JayTaylor's answer. stackoverflow.com/a/39776524/209942
4

For simple iteration can't we just check for additional arguments with "shift /1" at the end of the code and loop back? This will handle more than 10 arguments, upper limit not tested.

:loop

:: Your code using %1
echo %1

:: Check for further batch arguments.     
shift /1
IF [%1]==[] (
goto end
) ELSE (
goto loop
)

:end
pause

Comments

3
@ECHO OFF
SETLOCAL
SET nparms=0
FOR /l %%i IN (1,1,20) DO (
 SET myparm=%%i
 CALL :setparm %*
 IF DEFINED myparm SET nparms=%%i&CALL ECHO Parameter %%i=%%myparm%%
)
ECHO there were %nparms% parameters in %*
GOTO :EOF

:setparm
IF %myparm%==1 SET myparm=%1&GOTO :EOF
shift&SET /a myparm -=1&GOTO setparm
GOTO :eof

This should show how to extract random parameters by position.

2 Comments

Are you counting the number of command-line arguments?
@johnywhy No, that was done in the original post. This demonstration is of how to access any arbitrary parameter by position since for instance %13 to get the 13th parameter will actually tag "3" onto the end of the first parameter (%1) as only a single digit is allowed in this position. The demo shows the first 20 parameters as set by the for/l loop. The number in nparms is actually the last-detected parameter number that was defined. Change the loop to for %%i in (6,3,25,11,9) do and it will report the last parameter number defined of the set (6,3,25,11,9) as nparms

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.