How can I pass arguments to a batch file?

后端 未结 18 2156
陌清茗
陌清茗 2020-11-22 02:53

I need to pass an ID and a password to a batch file at the time of running rather than hardcoding them into the file.

Here\'s what the command line looks like:

相关标签:
18条回答
  • 2020-11-22 03:14
    FOR %%A IN (%*) DO (
        REM Now your batch file handles %%A instead of %1
        REM No need to use SHIFT anymore.
        ECHO %%A
    )
    

    This loops over the batch parameters (%*) either they are quoted or not, then echos each parameter.

    0 讨论(0)
  • 2020-11-22 03:14

    Inspired by an answer elsewhere by @Jon, I have crafted a more general algorithm for extracting named parameters, optional values, and switches.

    Let us say that we want to implement a utility foobar. It requires an initial command. It has an optional parameter --foo which takes an optional value (which cannot be another parameter, of course); if the value is missing it defaults to default. It also has an optional parameter --bar which takes a required value. Lastly it can take a flag --baz with no value allowed. Oh, and these parameters can come in any order.

    In other words, it looks like this:

    foobar <command> [--foo [<fooval>]] [--bar <barval>] [--baz]
    

    Here is a solution:

    @ECHO OFF
    SETLOCAL
    REM FooBar parameter demo
    REM By Garret Wilson
    
    SET CMD=%~1
    
    IF "%CMD%" == "" (
      GOTO usage
    )
    SET FOO=
    SET DEFAULT_FOO=default
    SET BAR=
    SET BAZ=
    
    SHIFT
    :args
    SET PARAM=%~1
    SET ARG=%~2
    IF "%PARAM%" == "--foo" (
      SHIFT
      IF NOT "%ARG%" == "" (
        IF NOT "%ARG:~0,2%" == "--" (
          SET FOO=%ARG%
          SHIFT
        ) ELSE (
          SET FOO=%DEFAULT_FOO%
        )
      ) ELSE (
        SET FOO=%DEFAULT_FOO%
      )
    ) ELSE IF "%PARAM%" == "--bar" (
      SHIFT
      IF NOT "%ARG%" == "" (
        SET BAR=%ARG%
        SHIFT
      ) ELSE (
        ECHO Missing bar value. 1>&2
        ECHO:
        GOTO usage
      )
    ) ELSE IF "%PARAM%" == "--baz" (
      SHIFT
      SET BAZ=true
    ) ELSE IF "%PARAM%" == "" (
      GOTO endargs
    ) ELSE (
      ECHO Unrecognized option %1. 1>&2
      ECHO:
      GOTO usage
    )
    GOTO args
    :endargs
    
    ECHO Command: %CMD%
    IF NOT "%FOO%" == "" (
      ECHO Foo: %FOO%
    )
    IF NOT "%BAR%" == "" (
      ECHO Bar: %BAR%
    )
    IF "%BAZ%" == "true" (
      ECHO Baz
    )
    
    REM TODO do something with FOO, BAR, and/or BAZ
    GOTO :eof
    
    :usage
    ECHO FooBar
    ECHO Usage: foobar ^<command^> [--foo [^<fooval^>]] [--bar ^<barval^>] [--baz]
    EXIT /B 1
    
    • Use SETLOCAL so that the variables don't escape into the calling environment.
    • Don't forget to initialize the variables SET FOO=, etc. in case someone defined them in the calling environment.
    • Use %~1 to remove quotes.
    • Use IF "%ARG%" == "" and not IF [%ARG%] == [] because [ and ] don't play will at all with values ending in a space.
    • Even if you SHIFT inside an IF block, the current args such as %~1 don't get updated because they are determined when the IF is parsed. You could use %~1 and %~2 inside the IF block, but it would be confusing because you had a SHIFT. You could put the SHIFT at the end of the block for clarity, but that might get lost and/or confuse people as well. So "capturing" %~1 and %~1 outside the block seems best.
    • You don't want to use a parameter in place of another parameter's optional value, so you have to check IF NOT "%ARG:~0,2%" == "--".
    • Be careful only to SHIFT when you use one of the parameters.
    • The duplicate code SET FOO=%DEFAULT_FOO% is regrettable, but the alternative would be to add an IF "%FOO%" == "" SET FOO=%DEFAULT_FOO% outside the IF NOT "%ARG%" == "" block. However because this is still inside the IF "%PARAM%" == "--foo" block, the %FOO% value would have been evaluated and set before you ever entered the block, so you would never detect that both the --foo parameter was present and also that the %FOO% value was missing.
    • Note that ECHO Missing bar value. 1>&2 sends the error message to stderr.
    • Want a blank line in a Windows batch file? You gotta use ECHO: or one of the variations.
    0 讨论(0)
  • 2020-11-22 03:14

    For to use looping get all arguments and in pure batch:

    Obs: For using without: ?*&<>


    @echo off && setlocal EnableDelayedExpansion
    
     for %%Z in (%*)do set "_arg_=%%Z" && set/a "_cnt+=1+0" && (
         call set "_arg_[!_cnt!]=!_arg_!" && for /l %%l in (!_cnt! 1 !_cnt!
         )do echo/ The argument n:%%l is: !_arg_[%%l]!
     )
    
    goto :eof 
    

    Your code is ready to do something with the argument number where it needs, like...

     @echo off && setlocal EnableDelayedExpansion
    
     for %%Z in (%*)do set "_arg_=%%Z" && set/a "_cnt+=1+0" && call set "_arg_[!_cnt!]=!_arg_!"
     
     fake-command /u !_arg_[1]! /p !_arg_[2]! > test-log.txt
     
    
    0 讨论(0)
  • 2020-11-22 03:16

    I wrote a simple read_params script that can be called as a function (or external .bat) and will put all variables into the current environment. It won't modify the original parameters because the function is being called with a copy of the original parameters.

    For example, given the following command:

    myscript.bat some -random=43 extra -greeting="hello world" fluff
    

    myscript.bat would be able to use the variables after calling the function:

    call :read_params %*
    
    echo %random%
    echo %greeting%
    

    Here's the function:

    :read_params
    if not %1/==/ (
        if not "%__var%"=="" (
            if not "%__var:~0,1%"=="-" (
                endlocal
                goto read_params
            )
            endlocal & set %__var:~1%=%~1
        ) else (
            setlocal & set __var=%~1
        )
        shift
        goto read_params
    )
    exit /B
    

    Limitations

    • Cannot load arguments with no value such as -force. You could use -force=true but I can't think of a way to allow blank values without knowing a list of parameters ahead of time that won't have a value.

    Changelog

    • 2/18/2016
      • No longer requires delayed expansion
      • Now works with other command line arguments by looking for - before parameters.
    0 讨论(0)
  • 2020-11-22 03:19

    Paired arguments

    If you prefer passing the arguments in a key-value pair you can use something like this:

    @echo off
    
    setlocal enableDelayedExpansion
    
    :::::  asigning arguments as a key-value pairs:::::::::::::
    set counter=0
    for %%# in (%*) do (    
        set /a counter=counter+1
        set /a even=counter%%2
        
        if !even! == 0 (
            echo setting !prev! to %%#
            set "!prev!=%%~#"
        )
        set "prev=%%~#"
    )
    ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    
    :: showing the assignments
    echo %one% %two% %three% %four% %five%
    
    endlocal
    

    And an example :

    c:>argumentsDemo.bat one 1 "two" 2 three 3 four 4 "five" 5
    1 2 3 4 5
    

    Predefined variables

    You can also set some environment variables in advance. It can be done by setting them in the console or setting them from my computer:

    @echo off
    
    if defined variable1 (
        echo %variable1%
    )
    
    if defined variable2 (
        echo %variable2%
    )
    

    and calling it like:

    c:\>set variable1=1
    
    c:\>set variable2=2
    
    c:\>argumentsTest.bat
    1
    2
    

    File with listed values

    You can also point to a file where the needed values are preset. If this is the script:

    @echo off
    
    setlocal
    ::::::::::
    set "VALUES_FILE=E:\scripts\values.txt"
    :::::::::::
    
    
    for /f "usebackq eol=: tokens=* delims=" %%# in ("%VALUES_FILE%") do set "%%#"
    
    echo %key1% %key2% %some_other_key%
    
    endlocal
    

    and values file is this:

    :::: use EOL=: in the FOR loop to use it as a comment
    
    key1=value1
    
    key2=value2
    
    :::: do not left spaces arround the =
    :::: or at the begining of the line
    
    some_other_key=something else
    
    and_one_more=more
    

    the output of calling it will be:

    value1 value2 something else

    Of course you can combine all approaches. Check also arguments syntax , shift

    0 讨论(0)
  • 2020-11-22 03:22

    A friend was asking me about this subject recently, so I thought I'd post how I handle command-line arguments in batch files.

    This technique has a bit of overhead as you'll see, but it makes my batch files very easy to understand and quick to implement. As well as supporting the following structures:

    >template.bat [-f] [--flag] [/f] [--namedvalue value] arg1 [arg2][arg3][...]
    

    The jist of it is having the :init, :parse, and :main functions.

    Example usage

    >template.bat /?
    test v1.23
    This is a sample batch file template,
    providing command-line arguments and flags.
    
    USAGE:
    test.bat [flags] "required argument" "optional argument"
    
    /?, --help           shows this help
    /v, --version        shows the version
    /e, --verbose        shows detailed output
    -f, --flag value     specifies a named parameter value
    
    >template.bat          <- throws missing argument error
    (same as /?, plus..)
    ****                                   ****
    ****    MISSING "REQUIRED ARGUMENT"    ****
    ****                                   ****
    
    >template.bat -v
    1.23
    
    >template.bat --version
    test v1.23
    This is a sample batch file template,
    providing command-line arguments and flags.
    
    >template.bat -e arg1
    **** DEBUG IS ON
    UnNamedArgument:    "arg1"
    UnNamedOptionalArg: not provided
    NamedFlag:          not provided
    
    >template.bat --flag "my flag" arg1 arg2
    UnNamedArgument:    "arg1"
    UnNamedOptionalArg: "arg2"
    NamedFlag:          "my flag"
    
    >template.bat --verbose "argument #1" --flag "my flag" second
    **** DEBUG IS ON
    UnNamedArgument:    "argument #1"
    UnNamedOptionalArg: "second"
    NamedFlag:          "my flag"
    

    template.bat

    @::!/dos/rocks
    @echo off
    goto :init
    
    :header
        echo %__NAME% v%__VERSION%
        echo This is a sample batch file template,
        echo providing command-line arguments and flags.
        echo.
        goto :eof
    
    :usage
        echo USAGE:
        echo   %__BAT_NAME% [flags] "required argument" "optional argument" 
        echo.
        echo.  /?, --help           shows this help
        echo.  /v, --version        shows the version
        echo.  /e, --verbose        shows detailed output
        echo.  -f, --flag value     specifies a named parameter value
        goto :eof
    
    :version
        if "%~1"=="full" call :header & goto :eof
        echo %__VERSION%
        goto :eof
    
    :missing_argument
        call :header
        call :usage
        echo.
        echo ****                                   ****
        echo ****    MISSING "REQUIRED ARGUMENT"    ****
        echo ****                                   ****
        echo.
        goto :eof
    
    :init
        set "__NAME=%~n0"
        set "__VERSION=1.23"
        set "__YEAR=2017"
    
        set "__BAT_FILE=%~0"
        set "__BAT_PATH=%~dp0"
        set "__BAT_NAME=%~nx0"
    
        set "OptHelp="
        set "OptVersion="
        set "OptVerbose="
    
        set "UnNamedArgument="
        set "UnNamedOptionalArg="
        set "NamedFlag="
    
    :parse
        if "%~1"=="" goto :validate
    
        if /i "%~1"=="/?"         call :header & call :usage "%~2" & goto :end
        if /i "%~1"=="-?"         call :header & call :usage "%~2" & goto :end
        if /i "%~1"=="--help"     call :header & call :usage "%~2" & goto :end
    
        if /i "%~1"=="/v"         call :version      & goto :end
        if /i "%~1"=="-v"         call :version      & goto :end
        if /i "%~1"=="--version"  call :version full & goto :end
    
        if /i "%~1"=="/e"         set "OptVerbose=yes"  & shift & goto :parse
        if /i "%~1"=="-e"         set "OptVerbose=yes"  & shift & goto :parse
        if /i "%~1"=="--verbose"  set "OptVerbose=yes"  & shift & goto :parse
    
        if /i "%~1"=="--flag"     set "NamedFlag=%~2"   & shift & shift & goto :parse
    
        if not defined UnNamedArgument     set "UnNamedArgument=%~1"     & shift & goto :parse
        if not defined UnNamedOptionalArg  set "UnNamedOptionalArg=%~1"  & shift & goto :parse
    
        shift
        goto :parse
    
    :validate
        if not defined UnNamedArgument call :missing_argument & goto :end
    
    :main
        if defined OptVerbose (
            echo **** DEBUG IS ON
        )
    
        echo UnNamedArgument:    "%UnNamedArgument%"
    
        if defined UnNamedOptionalArg      echo UnNamedOptionalArg: "%UnNamedOptionalArg%"
        if not defined UnNamedOptionalArg  echo UnNamedOptionalArg: not provided
    
        if defined NamedFlag               echo NamedFlag:          "%NamedFlag%"
        if not defined NamedFlag           echo NamedFlag:          not provided
    
    :end
        call :cleanup
        exit /B
    
    :cleanup
        REM The cleanup function is only really necessary if you
        REM are _not_ using SETLOCAL.
        set "__NAME="
        set "__VERSION="
        set "__YEAR="
    
        set "__BAT_FILE="
        set "__BAT_PATH="
        set "__BAT_NAME="
    
        set "OptHelp="
        set "OptVersion="
        set "OptVerbose="
    
        set "UnNamedArgument="
        set "UnNamedArgument2="
        set "NamedFlag="
    
        goto :eof
    
    0 讨论(0)
提交回复
热议问题