1.

Solve : Help with command line arguments?

Answer»

Hello everyone. I'm trying to create a batch file which accepts a few commandline arguments. My problem is that I do not want to check for %1 or %2 etc, but for %* which means that the user should be able to specify the arguments regardless of their order.

Code: [Select]@ECHO OFF

IF /I "%*"=="1stARG" ECHO:1stARG&&GOTO :END
IF /I "%*"=="2ndARG" ECHO:2ndARG&&GOTO :END
IF /I "%*"=="3rdARG" ECHO:3rdARG&&GOTO :END
IF /I "%*"=="4thARG" ECHO:4rdARG&&GOTO :END
IF /I "%1"=="" ECHO:NO ARGUMENT SPECIFIED&&GOTO :END
ECHO:WRONG ARGUMENT&&GOTO :END

:END
PAUSE
The problem is that this way if I use "1stARG 2ndARG" it's not being split. So I guess I have to use a FOR loop. Basically I'm trying to find the simplest way of achieving this.

Thanks in advance for any help.You mentioned FOR so I deduce this is not about MS-DOS. You should be aware that in Windows bath scripting the double ampersand (&&) is not a simple command SEPARATOR (like in Unix). It is an errorlevel test. "Command1 && command2" means "execute command1 and if the errorlevel from command1 is zero, (and only if) then execute command2". The standard command separator where you want more than 1 command on a single line is the single ampersand (&) for example command1 & command2. Also you don't need to put the colon before the label identifier in a goto statement, and using all capital letters is not compulsory.

Quote

the user should be able to specify the arguments regardless of their order

Why? You are making the script unnecessarily complicated, and batch language is very bad at this sort of thing.

However you can use FOR to split the parameters up, assuming that each contains no spaces. This example uses numbers for the FOR metavariables; if you want more than ten (0-9) you'll have to use letters. The example assumes 3 parameters are expected

Code: [Select]@echo off
for /f "tokens=1-3 delims= " %%1 in ("%*") do (
set parameter1=%%1
set parameter2=%%2
set parameter3=%%3
)
set check=0
if "%parameter1%"=="" set /a check+=1
if "%parameter2%"=="" set /a check+=1
if "%parameter3%"=="" set /a check+=1
if %check% gtr 0 echo Wrong number of parameters & goto end
echo parameter 1 is %parameter1%
echo parameter 2 is %parameter2%
echo parameter 3 is %parameter3%
:end Quote
You mentioned FOR so I deduce this is not about MS-DOS. You should be aware that in Windows bath scripting the double ampersand (&&) is not a simple command separator (like in Unix). It is an errorlevel test. "Command1 && command2" means "execute command1 and if the errorlevel from command1 is zero, (and only if) then execute command2". The standard command separator where you want more than 1 command on a single line is the single ampersand (&) for example command1 & command2. Also you don't need to put the colon before the label identifier in a goto statement, and using all capital letters is not compulsory.

I'm aware of that, I'm just used to use this and since it works for my cases I never bothered with this. Thanks for reminding it me. As for the capital letters I simply prefer them for the dos commands.

Quote
Why? You are making the script unnecessarily complicated, and batch language is very bad at this sort of thing.

Well, even so I have to use batch for this since it's the only language I'm familiar with.

Here is what I'm trying to achieve. I need to be able to parse 2 commandline arguments but without having to use them in a specific order. So I can't check for the first or the second argument specifically. There must be a way to filter all the arguments with FIND and set the two vars I need.
My situation is more like this: Accept all days as one argument and all months as another one. If none of these are used then error out. The second part is easy

I know it's difficult and that batch isn't the best way to do it, but I have to stick to it, unfortunately.Code: [Select]
@echo off
setlocal enabledelayedexpansion

set errormessage=1 day and 1 month not supplied

REM split parameters into two tokens
for /f "tokens=1-3 delims= " %%1 in ("%*") do (
set parameter1=%%1
set parameter2=%%2
)

REM check for blank arguments
set check=0
if "%parameter1%"=="" set /a check+=1
if "%parameter2%"=="" set /a check+=1
if %check% gtr 0 echo %errormessage% & goto end

REM check for 1 day and 1 month
set days=0
set months=0
for %%A in (%parameter1% %parameter2%) do (
echo %%A | FINDSTR /I "Monday Tuesday Wednesday Thursday Friday Saturday Sunday">nul && (
set /a days+=1
set day=%%A
)
echo %%A | findstr /I "January February March April May June July August September October November December">nul && (
set /a months+=1
set month=%%A
)
)
if not %days% equ 1 echo %errormessage% & goto end
if not %months% equ 1 echo %errormessage% & goto end

echo day: %day%
echo month: %month%

:end

Like I have told you 10 times already, you are the best! This is what I was looking for. Except for a minor change I need to make. I want to handle the case where no arguments are specified (or one of the two isn't) a little different, use the default values in this case (Monday/January in our example). But also keep the check for invalid arguments like it is now.

Thank you very much, without your help I would be lost in the ocean Try this

Code: [Select]@echo off
setlocal enabledelayedexpansion

set monthlist=January February March April May June July August September October November December
set daylist=Monday Tuesday Wednesday Thursday Friday Saturday Sunday
set DefaultDay=Monday
set DefaultMonth=January

REM split parameters into two tokens
for /f "tokens=1-3 delims= " %%1 in ("%*") do (
set parameter1=%%1
set parameter2=%%2
)

set days=0
set months=0
for %%A in (%parameter1% %parameter2%) do (
echo %%A | findstr /I "%daylist%">nul && (
set /a days+=1
set day=%%A
)
echo %%A | findstr /I "%monthlist%">nul && (
set /a months+=1
set month=%%A
)
)
if %days% equ 0 set day=%DefaultDay%
if %months% equ 0 set month=%DefaultMonth%

echo day: %day%
echo month: %month%
Thanks for your reply. Now, this approach is using the default values correctly and it's cleaner. But there's a problem with the FINSTR command.
If I use "Mondayy" it will return this value. I think this can be solved by using \ etc.
That's why I want to make it error out if any of the two arguments is not one of those in the list so that it doesn't use the default silently but only when one or none of the arguments is specified.Could you tell me why it is so important that the parameters need to be presented in any order?
I think I must be MISSING something, but couldn't shift be used for this in some capacity?Quote from: BC_Programmer on January 30, 2011, 10:45:20 AM
I think I must be missing something, but couldn't shift be used for this in some capacity?

Shift will get over having more than the 9 arguments allowed by the %1 to %9 parameters. Here we only have a fixed number. I am not sure if the OP is using "months" and "days" as generic examples for them, and whether there are going to be more than 2 in the finished script. We don't actually need to split %* - %1 and %2 will do just fine.


Quote from: Salmon Trout on January 30, 2011, 09:51:29 AM
Could you tell me why it is so important that the parameters need to be presented in any order?
I need to eliminate the case where someone uses the arguments in the wrong order. Currently I only have 2 arguments, but if it works I think I will be able to extent it for more

Your last code is ALMOST what I need, I just need it to check for invalid arguments and error out. I'll see if I can make FINDSTR to work only with the specific string and not any string that contains the words in the list.

Thank you very much for your help.


Discussion

No Comment Found