How to check command line parameter in “.bat” file?

后端 未结 7 2052
无人共我
无人共我 2020-12-13 02:00

My OS is Windows Vista. I need to have a \".bat\" file where I need to check if user enters any command-line parameter or not. If does then if the parameter equals to

相关标签:
7条回答
  • 2020-12-13 02:18

    The short answer - use square brackets:

    if [%1]==[] goto :blank
    

    or (when you need to handle quoted args, see the Edit below):

    if [%~1]==[] goto :blank
    

    Why? you might ask. Well, just as Jeremiah Willcock mentioned: http://ss64.com/nt/if.html - they use that! OK, but what's wrong with the quotes?

    Again, short answer: they are "magical" - sometimes double (double) quotes get converted to a single (double) quote. And they need to match, for a start.

    Consider this little script:

    @rem argq.bat
    @echo off
    
    :loop 
    if "%1"=="" goto :done
    echo %1
    shift
    goto :loop
    
    :done
    echo Done.
    

    Let's test it:

    C:\> argq bla bla
    bla
    bla
    Done.
    

    Seems to work. But now, lets switch to second gear:

    C:\> argq "bla bla"
    bla""=="" was unexpected at this time.
    

    Boom This didn't evaluate to true, neither did it evaluate to false. The script DIED. If you were supposed to turn off the reactor somewhere down the line, well - tough luck. You now will die like Harry Daghlian.

    You may think - OK, the arguments can't contain quotes. If they do, this happens. Wrong Here's some consolation:

    C:\> argq ""bla bla""
    ""bla
    bla""
    Done.
    

    Oh yeah. Don't worry - sometimes this will work.

    Let's try another script:

    @rem args.bat
    @echo off
    
    :loop 
    if [%1]==[] goto :done
    echo %1
    shift
    goto :loop
    
    :done
    echo Done.
    

    You can test yourself, that it works OK for the above cases. This is logical - quotes have nothing to do with brackets, so there's no magic here. But what about spicing the args up with brackets?

    D:\>args ]bla bla[
    ]bla
    bla[
    Done.
    
    D:\>args [bla bla]
    [bla
    bla]
    Done.
    

    No luck there. The brackets just can't choke cmd.exe's parser.

    Let's go back to the evil quotes for a moment. The problem was there, when the argument ended with a quote:

    D:\>argq "bla1 bla2"
    bla2""=="" was unexpected at this time.
    

    What if I pass just:

    D:\>argq bla2"
    The syntax of the command is incorrect.
    

    The script won't run at all. Same for args.bat:

    D:\>args bla2"
    The syntax of the command is incorrect.
    

    But what do I get, when the number of "-characters "matches" (i.e. - is even), in such a case:

    D:\>args bla2" "bla3
    bla2" "bla3
    Done.
    

    NICE - I hope you learned something about how .bat files split their command line arguments (HINT: *It's not exactly like in bash). The above argument contains a space. But the quotes are not stripped automatically.

    And argq? How does it react to that? Predictably:

    D:\>argq bla2" "bla3
    "bla3"=="" was unexpected at this time.
    

    So - think before you say: "Know what? Just use quotes. [Because, to me, this looks nicer]".

    Edit

    Recently, there were comments about this answer - well, sqare brackets "can't handle" passing quoted arguments and treating them just as if they weren't quoted.

    The syntax:

    if "%~1"=="" (...)
    

    Is not some newly found virtue of the double quotes, but a display of a neat feature of stripping quotes from the argument variable, if the first and last character is a double quote.

    This "technology" works just as well with square brackets:

    if [%~1]==[] (...)
    

    It was a useful thing to point this out, so I also upvote the new answer.

    Finally, double quote fans, does an argument of the form "" exist in your book, or is it blank? Just askin' ;)

    0 讨论(0)
  • 2020-12-13 02:21

    I've been struggling recently with the implementation of complex parameter switches in a batch file so here is the result of my research. None of the provided answers are fully safe, examples:

    "%1"=="-?" will not match if the parameter is enclosed in quotes (needed for file names etc.) or will crash if the parameter is in quotes and has spaces (again often seen in file names)

    @ECHO OFF
    SETLOCAL
    echo.
    echo starting parameter test...
    echo.
    rem echo First parameter is %1
    if "%1"=="-?" (echo Condition is true, param=%1) else (echo Condition is false, param=%1)
    C:\>test.bat -?
    
    starting parameter test...
    
    Condition is true, param=-?
    
    C:\>test.bat "-?"
    
    starting parameter test...
    
    Condition is false, param="-?"
    

    Any combination with square brackets [%1]==[-?] or [%~1]==[-?] will fail in case the parameter has spaces within quotes:

    @ECHO OFF
    SETLOCAL 
    echo.
    echo starting parameter test...
    echo.
    echo First parameter is %1
    if [%~1]==[-?] (echo Condition is true, param=%1) else (echo Condition is false, param=%1)
    
    C:\>test.bat "long file name"
    
    starting parameter test...
    
    First parameter is "long file name"
    file was unexpected at this time.
    

    The proposed safest solution "%~1"=="-?" will crash with a complex parameter that includes text outside the quotes and text with spaces within the quotes:

    @ECHO OFF
    SETLOCAL 
    echo.
    echo starting parameter test...
    echo.
    echo First parameter is %1
    if "%~1"=="-?" (echo Condition is true, param=%1) else (echo Condition is false, param=%1)
    
    C:\>test.bat -source:"long file name"
    
    starting parameter test...
    
    First parameter is -source:"long file name"
    file was unexpected at this time.
    

    The only way to ensure all above scenarios are covered is to use EnableDelayedExpansion and to pass the parameters by reference (not by value) using variables. Then even the most complex scenario will work fine:

    @ECHO OFF
    SETLOCAL EnableDelayedExpansion
    echo.
    echo starting parameter test...
    echo.
    echo First parameter is %1
    :: we assign the parameter to a variable to pass by reference with delayed expansion
    set "var1=%~1"
    echo var1 is !var1!
    :: we assign the value to compare with to a second variable to pass by reference with delayed expansion
    set "var2=-source:"c:\app images"\image.png"
    echo var2 is !var2!
    if "!var1!"=="!var2!" (echo Condition is true, param=!var1!) else (echo Condition is false, param=!var1!)
    C:\>test.bat -source:"c:\app images"\image.png
    
    starting parameter test...
    
    First parameter is -source:"c:\app images"\image.png
    var1 is -source:"c:\app images"\image.png
    var2 is -source:"c:\app images"\image.png
    Condition is true, param=-source:"c:\app images"\image.png
    
    C:\>test.bat -source:"c:\app images"\image1.png
    
    starting parameter test...
    
    First parameter is -source:"c:\app images"\image1.png
    var1 is -source:"c:\app images"\image1.png
    var2 is -source:"c:\app images"\image.png
    Condition is false, param=-source:"c:\app images"\image1.png
    
    C:\>test.bat -source:"c:\app images\image.png"
    
    starting parameter test...
    
    First parameter is -source:"c:\app images\image.png"
    var1 is -source:"c:\app images\image.png"
    var2 is -source:"c:\app images"\image.png
    Condition is false, param=-source:"c:\app images\image.png"
    
    0 讨论(0)
  • 2020-12-13 02:22

    In addition to the other answers, which I subscribe, you may consider using the /I switch of the IF command.

    ... the /I switch, if specified, says to do case insensitive string compares.

    it may be of help if you want to give case insensitive flexibility to your users to specify the parameters.

    IF /I "%1"=="-b" GOTO SPECIFIC
    
    0 讨论(0)
  • 2020-12-13 02:23

    Look at http://ss64.com/nt/if.html for an answer; the command is IF [%1]==[] GOTO NO_ARGUMENT or similar.

    0 讨论(0)
  • 2020-12-13 02:28

    You are comparing strings. If an arguments are omitted, %1 expands to a blank so the commands become IF =="-b" GOTO SPECIFIC for example (which is a syntax error). Wrap your strings in quotes (or square brackets).

    REM this is ok
    IF [%1]==[/?] GOTO BLANK
    
    REM I'd recommend using quotes exclusively
    IF "%1"=="-b" GOTO SPECIFIC
    
    IF NOT "%1"=="-b" GOTO UNKNOWN
    
    0 讨论(0)
  • 2020-12-13 02:30

    You need to check for the parameter being blank: if "%~1"=="" goto blank

    Once you've done that, then do an if/else switch on -b: if "%~1"=="-b" (goto specific) else goto unknown

    Surrounding the parameters with quotes makes checking for things like blank/empty/missing parameters easier. "~" ensures double quotes are stripped if they were on the command line argument.

    0 讨论(0)
提交回复
热议问题