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

前端 未结 9 1721
情话喂你
情话喂你 2021-01-30 20:35

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

相关标签:
9条回答
  • 2021-01-30 20:54

    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
    
    0 讨论(0)
  • 2021-01-30 20:55

    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
    
    0 讨论(0)
  • 2021-01-30 20:59

    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_*
    
    0 讨论(0)
  • 2021-01-30 21:04
    :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

    0 讨论(0)
  • 2021-01-30 21:08

    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:

    • fexible, 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 behaviour so they get something like null or undefined instead of empty)

    Enjoy.

    0 讨论(0)
  • 2021-01-30 21:10

    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
    
    0 讨论(0)
提交回复
热议问题