Is there a way to pass parameters "by name" (and not by order) to a batch .bat file?

Batch File

Batch File Problem Overview


I need to be able to pass parameters to a windows batch file BY NAME (and NOT by order). My purpose here is to give end user the flexibility to pass parameters in any order, and the batch file should still be able to process them.

An example to make my question clearer:

in the command line, user does the following: somebatchfile.bat originalFile.txt newFile.txt

Inside somebatchfile.bat there is a simple statement to copy the contents of original file (first parameter %1%) to the new file (second parameter %2%). It could be as simple as the following statement: copy %1% %2%

Now, if user passes the above parameters in reverse order, the result will be far from desirable (very WRONG in fact).

So, is there a way for user to pass parameters by name: e.g. somebatchfile.bat "SOURC=originalFile.txt" "TARGET=newFile.txt" and for script to recognize them and use'em in correct places e.g. copy %SOURCE% %TARGET%?

Thanks,

Batch File Solutions


Solution 1 - Batch File

Yeah you could do something like that though I don't think you can use "=" as a token delimiter. You could use say a colon ":", somebatchfile.bat "SOURC:originalFile.txt" "TARGET:newFile.txt". Here is an example of how you might split the tokens:

@echo off

set foo=%1
echo input: %foo%

for /f "tokens=1,2 delims=:" %%a in ("%foo%") do set name=%%a & set val=%%b

echo name:  %name%
echo value: %val%

Running this would produce this:

C:\>test.bat SOURC:originalFile.txt
input: SOURC:originalFile.txt
name:  SOURC
value: originalFile.txt

[Edit]

Ok, maybe it was too close to bed time for me last night but looking again this morning, you can do this:

@echo off

set %1
set %2

echo source: %SOURCE%
echo target: %TARGET%

Which would produce this (note that I reversed the source and target on the command line to show they are set and retrieved correctly):

C:\>test.bat "TARGET=newFile.txt" "SOURCE=originalFile.txt"
source: originalFile.txt
target: newFile.txt

Note that %1 and %2 are evaluated before the set so these do get set as environment variables. They must however be quoted on the command line.

Solution 2 - Batch File

Other way I quite liked:

set c=defaultC
set s=defaultS
set u=defaultU

:initial
if "%1"=="" goto done
echo              %1
set aux=%1
if "%aux:~0,1%"=="-" (
   set nome=%aux:~1,250%
) else (
   set "%nome%=%1"
   set nome=
)
shift
goto initial
:done

echo %c%
echo %s%
echo %u%

Run the following command:

arguments.bat -c users -u products

Will generate the following output:

users
defaultS
products

Solution 3 - Batch File

A bit late to the party :) This is my suggestion for managing "posix like" options. For example mybatchscript.bat -foo=foovalue -bar=barvalue -flag

:parseArgs
:: asks for the -foo argument and store the value in the variable FOO
call:getArgWithValue "-foo" "FOO" "%~1" "%~2" && shift && shift && goto :parseArgs

:: asks for the -bar argument and store the value in the variable BAR
call:getArgWithValue "-bar" "BAR" "%~1" "%~2" && shift && shift && goto :parseArgs

:: asks for the -flag argument. If exist set the variable FLAG to "TRUE"
call:getArgFlag "-flag" "FLAG" "%~1" && shift && goto :parseArgs


:: your code here ...
echo FOO: %FOO%
echo BAR: %BAR%
echo FLAG: %FLAG%

goto:eof

..and here the functions that do the job. You should put them in the same batch file

:: =====================================================================
:: This function sets a variable from a cli arg with value
:: 1 cli argument name
:: 2 variable name
:: 3 current Argument Name
:: 4 current Argument Value
:getArgWithValue
if "%~3"=="%~1" (
  if "%~4"=="" (
    REM unset the variable if value is not provided
    set "%~2="
    exit /B 1
  )
  set "%~2=%~4"
  exit /B 0
)
exit /B 1
goto:eof



:: =====================================================================
:: This function sets a variable to value "TRUE" from a cli "flag" argument
:: 1 cli argument name
:: 2 variable name
:: 3 current Argument Name
:getArgFlag
if "%~3"=="%~1" (
  set "%~2=TRUE"
  exit /B 0
)
exit /B 1
goto:eof

Save the file as mybatchscript.bat and run

mybatchscript.bat -bar=barvalue -foo=foovalue -flag

You'll get:

FOO: foovalue
BAR: barvalue
FLAG: TRUE

Solution 4 - Batch File

I wanted to see the possibility of reading named parameter supplied to a batch program. For example :

myBatch.bat arg1  arg2 

Reading parameter can be done as follows :

%~1 would be arg1
%~2 would be arg2

Above argument supplied to batch program is easy to read but then each time you execute it, you have to maintain order and remember what arg1 is supposed to have. In order to overcome it, parameter can be supplied as key:value format. And command would look like below :

mybatch.bar key1:value1 key2:value2

Though there is no straight forward way to parse such argument list. I wrote following nested for loop in batch script which will basically parse and create environment variable with key1 as name, and value1 assigned to it. This way you can read all argument supplied using straight forward way of reading environment variable.

@echo off
FOR %%A IN (%*) DO (
   FOR /f "tokens=1,2 delims=:" %%G IN ("%%A") DO setLocal %%G=%%H
)

Afterwards, you can use %key1% format to read all argument being supplied.

HTH

Solution 5 - Batch File

Very old question, but I think I found a neat way (with no external dependencies) of passing key=value arguments to a batch file. You can test the method with the following MWE:

@echo off
chcp 65001

rem name this file test.bat and call it with something like:
rem test keyc=foo keyd=bar whatever keya=123 keyf=zzz

setlocal enabledelayedexpansion

set "map=%*"
call :gettoken keya var1
call :gettoken keyb var2
call :gettoken keyc var3

rem replace the following block with your real batch
rem ************************************************
echo:
echo Map is "%map%"
echo Variable var1 is "%var1%"
echo Variable var2 is "%var2%"
echo Variable var3 is "%var3%"
echo:
echo Done.
echo:
pause
rem ************************************************

goto :eof
:gettoken
call set "tmpvar=%%map:*%1=%%"
if "%tmpvar%"=="%map%" (set "%~2=") else (
for /f "tokens=1 delims= " %%a in ("%tmpvar%") do set tmpvar=%%a
set "%~2=!tmpvar:~1!"
)
exit /b

The method is quite:

  • flexible, because key=value arguments can be mixed with other arguments (such as filenames), and because the name of the variable used to store the value is independent from the name of key
  • scalable, because it's easy to add keys
  • robust, because anything passed that is not allowed by defined keys is ignored, and unassigned keys get an empty value (if you want you can easily change this behavior so they get something like null or undefined instead of empty)

A drawback is that it get confused if a key has a name that is part of another key name. So, for example, if you have a key like width, don't define a key like newwidth.

Enjoy.

Solution 6 - Batch File

Take this attempt (pure batch):

set PARAM_0=0
:parameters_parse

set parameter=%~1
if "%parameter%"=="" goto parameters_parse_done
if "%parameter:~0,1%"=="-" (
	set ARG_%parameter:~1%="%~2"
	shift
	shift
	goto parameters_parse
)
if "%parameter:~0,1%"=="/" (
	set ARG_%parameter:~1%="%~2"
	shift
	shift
	goto parameters_parse
)
set /a PARAM_0=%PARAM_0%+1
set PARAM_%PARAM_0%="%~1"
shift
goto parameters_parse

:parameters_parse_done

rem Insert your script here

and some tests:

call args.bat /bar="Hello World" Test1 -baz "Test test test" /foo=Test1 Test2

echo foo=%ARG_foo%
echo bar=%ARG_bar%
echo baz=%ARG_baz%
echo count=%PARAM_0%
echo 1=%PARAM_1%
echo 2=%PARAM_2%

Outputs:

foo="Test1"
bar="Hello World"
baz="Test test test"
count=2
1="Test1"
2="Test2"

Solution 7 - Batch File

I think you are looking for getopt kind of support in Windows batch scripts which unfortunately doesn't exist in entirety. The closest you can probably get is using GetOpt.btm script. With this then you can execute your script using command:

somebatchfile.bat /SOURC:originalFile.txt /TARGET:newFile.txt

Code:

@echo off
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:: GetOpt - Process command line options
:: 
:: Michael Fross
:: [email]michael@fross.org[/email]
:: [url]http://fross.org[/url]
::
:: This program scans the command line sent to it and sets various 
:: environment variables that coorespond to the settings.
::
:: It sets an OPTION_arg variable for each arg on the command line.
:: If a switch, the env var is set to 1.  If a value is given via the colon sign,
:: it's set to that value.  Note, there can not be any white space around the ':'
::
:: Use "If defined OPTION_arg" or "If %OPTION_arg eq value" to test for options
::
:: It also sets a parameter variable for each paramater entered: PARAM_1 to PARAM_n
:: PARAM_0 is a special value that contains the number of PARAMs.  Useful for looping
:: through all of them.  For example, do i = 1 to %PARAM_0 by 1 ...
::
:: In your batch file call getopt as:
::      call GetOpt.btm %$
::
:: I also recommend setting setlocal and endlocal in the host batch file so that
:: the option / param variable do not stick around after the host batch files exits.
::
:: Example usage:  BatchFile.btm /a /b:22 /longopt Parm1 Parm2 /quotedArg:"long quoted arg"
::   OPTION_a will equal 1.
::   OPTION_b will equal 22
::   OPTION_quotedArg will equal "long quoted arg"
::   OPTION_longopt will eqal 1.
::   PARAM_1 will equal Parm1
::   PARAM_2 will equal Parm2
::   PARAM_0 will be set to the number of parms, so 2 in this case
::
:: To get debug messages, set DEBUG=1.  This will give detailed information for each
:: parameter on the command line as getopt loops through the list.
::
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

:: Clean up the environment before we get going
unset getopt* OPTION_* PARAM_*
set getopt_ParmCounter=1

:: If in debug mode, kick off the display by showing the number of arguments
if defined DEBUG echo GetOpt is processing %# arguments:

:: Loop through all command line arguments one at a time.
for /L %i in (1,1,%#) do (
   if defined DEBUG (echo. %+ echo Scan #%i:)

   :: If first character starts with a - or / it must be an option
   iff %@instr[0,1,%[%i]] == - .or. %@instr[0,1,%[%i]] == / then
	  set getopt_Parm=%[%i]
	  if defined DEBUG echo  - Item "%getopt_Parm" is an option.

	  :: Set the Equal Index to the position of the colon.  0 means none was found
	  set getopt_EqIdx=%@index[%getopt_Parm,:]

	  :: Display the index position of the colon
	  if defined DEBUG .AND. %getopt_EqIdx GE 0 echo  - Found colon at index position "%getopt_EqIdx"

	  :: If the index is GE 0 then we must have a colon in the option.
	  :: set the OPTION value to the stuff to the right of the colon
	  iff %getopt_EqIdx ge 0 then
		 set getopt_ParmName=%@instr[2, %@Dec[%getopt_EqIdx] , %getopt_Parm]
		 if defined DEBUG echo  - ParmName  = "%getopt_ParmName"
		 set getopt_ParmValue=%@right[%@eval[-%getopt_EqIdx-1],%getopt_Parm]
		 if defined DEBUG echo  - Parmvalue = "%getopt_ParmValue"
		 set OPTION_%getopt_ParmName=%getopt_ParmValue
	  else
		 :: This is a flag, so simply set the value to 1
		 if defined DEBUG echo  - No colon found in "%getopt_Parm"
		 set getopt_ParmName=%@right[%@Dec[%@len[%getopt_Parm]],%getopt_Parm]
		 set getopt_ParmValue=1
		 if defined DEBUG echo  - ParmName = "%getopt_ParmName"
		 set OPTION_%getopt_ParmName=%getopt_ParmValue
	  endiff

	  :: Regardless if there was a value or not, display what is going to occur
	  if defined DEBUG echo  - Setting Variable OPTION_%getopt_ParmName=%getopt_ParmValue
   else
	  :: There was no / or - found, therefore this must be a paramater, not an option
	  if defined DEBUG echo  - "%[%i]" is a parameter, not an option
	  set PARAM_%getopt_ParmCounter=%[%i]
	  set PARAM_0=%getopt_ParmCounter
	  if defined DEBUG echo  - Updating Number of Parms.  PARAM_0=%PARAM_0
	  if defined DEBUG echo  - Setting Variable PARAM_%getopt_ParmCounter = %[%i]
	  set getopt_ParmCounter=%@Inc[%getopt_ParmCounter]
   endiff
)

:: Display additional information
iff defined DEBUG then
   echo.
   echo There were %PARAM_0 parameters found.  Setting PARAM_0=%PARAM_0
   echo.
   echo GetOpt has completed processing %# arguments.  Ending Execution.
endiff

:: Perform cleanup
unset getopt_*

Solution 8 - Batch File

My gosh people; You're overthinking this! :)

OP's CMD args are all in the form "[VarName]=[Something]"

So the 1st line could simply be FOR %%_ IN (%*) DO SET "%%~_"

or in nicer looking code

FOR %%_ IN (%*) DO SET "%%~_"

That said here is a more complete script example where you could just put all of your script within the :Main function

@( Setlocal
  ECHO OFF
  FOR %%_ IN (%*) DO SET "%%~_"
)

CALL :Main

( ENDLOCAL
  EXIT /B )

:Main
  REM Your code goes here.
  REM Your code goes here.
  REM Your code goes here.
  REM Your code goes here.
GOTO :EOF

Solution 9 - Batch File

:parse
IF "%~1"=="" GOTO endparse
ECHO "%~1"| FIND /I "=" && SET "%~1"
SHIFT /1
GOTO parse
:endparse

This code checks all the parameters, strips all the outer quotes, and if equal sign is present, sets variable to value.

Use it like this:

yourbatch.bat "foo=bar" "foo2=bar2"

based on this answer: Using parameters in batch files at DOS command line, and edited in response to the edit attempt by D.Barev

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionPouyaView Question on Stackoverflow
Solution 1 - Batch FileDave RagerView Answer on Stackoverflow
Solution 2 - Batch FileDavidson AlencarView Answer on Stackoverflow
Solution 3 - Batch FileFederico DestefanisView Answer on Stackoverflow
Solution 4 - Batch FileGaurav DagaView Answer on Stackoverflow
Solution 5 - Batch FilemmjView Answer on Stackoverflow
Solution 6 - Batch FilePiotrKView Answer on Stackoverflow
Solution 7 - Batch FileanubhavaView Answer on Stackoverflow
Solution 8 - Batch FileBen PersonickView Answer on Stackoverflow
Solution 9 - Batch FilerobotikView Answer on Stackoverflow