Using parameters in batch files at Windows command line

Using parameters in batch files: %0 and %9

Batch files can refer to the words passed in as parameters with the tokens: %0 to %9.

%0 is the program name as it was called.
%1 is the first command line parameter
%2 is the second command line parameter
and so on till %9.

parameters passed in on the commandline must be alphanumeric characters and delimited by spaces. Since %0 is the program name as it was called, in DOS %0 will be empty for AUTOEXEC.BAT if started at boot time.

Example:

Put the following command in a batch file called mybatch.bat:

@echo off
@echo hello %1 %2
pause

Invoking the batch file like this: mybatch john billy would output:

hello john billy

Get more than 9 parameters for a batch file, use: %*

The Percent Star token %* means "the rest of the parameters". You can use a for loop to grab them, as defined here:

http://www.robvanderwoude.com/parameters.php

Notes about delimiters for batch parameters

Some characters in the command line parameters are ignored by batch files, depending on the DOS version, whether they are "escaped" or not, and often depending on their location in the command line:

commas (",") are replaced by spaces, unless they are part of a string in 
double quotes

semicolons (";") are replaced by spaces, unless they are part of a string in 
double quotes

"=" characters are sometimes replaced by spaces, not if they are part of a 
string in double quotes

the first forward slash ("/") is replaced by a space only if it immediately 
follows the command, without a leading space

multiple spaces are replaced by a single space, unless they are part of a 
string in double quotes

tabs are replaced by a single space

leading spaces before the first command line argument are ignored

@Jon's :parse/:endparse scheme is a great start, and he has my gratitude for the initial pass, but if you think that the Windows torturous batch system would let you off that easy… well, my friend, you are in for a shock. I have spent the whole day with this devilry, and after much painful research and experimentation I finally managed something viable for a real-life utility.

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]

Complicated? No, that seems pretty typical of real life utilities. (git anyone?)

Without further ado, 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

Yes, it really is that bad. See my similar post at https://stackoverflow.com/a/50653047/421049, where I provide more analysis of what is going on in the logic, and why I used certain constructs.

Hideous. Most of that I had to learn today. And it hurt.


Batch Files automatically pass the text after the program so long as their are variables to assign them to. They are passed in order they are sent; e.g. %1 will be the first string sent after the program is called, etc.

If you have Hello.bat and the contents are:

@echo off
echo.Hello, %1 thanks for running this batch file (%2)
pause

and you invoke the batch in command via

hello.bat APerson241 %date%

you should receive this message back:

Hello, APerson241 thanks for running this batch file (01/11/2013)


As others have already said, parameters passed through the command line can be accessed in batch files with the notation %1 to %9. There are also two other tokens that you can use:

  • %0 is the executable (batch file) name as specified in the command line.
  • %* is all parameters specified in the command line -- this is very useful if you want to forward the parameters to another program.

There are also lots of important techniques to be aware of in addition to simply how to access the parameters.

Checking if a parameter was passed

This is done with constructs like IF "%~1"=="", which is true if and only if no arguments were passed at all. Note the tilde character which causes any surrounding quotes to be removed from the value of %1; without a tilde you will get unexpected results if that value includes double quotes, including the possibility of syntax errors.

Handling more than 9 arguments (or just making life easier)

If you need to access more than 9 arguments you have to use the command SHIFT. This command shifts the values of all arguments one place, so that %0 takes the value of %1, %1 takes the value of %2, etc. %9 takes the value of the tenth argument (if one is present), which was not available through any variable before calling SHIFT (enter command SHIFT /? for more options).

SHIFT is also useful when you want to easily process parameters without requiring that they are presented in a specific order. For example, a script may recognize the flags -a and -b in any order. A good way to parse the command line in such cases is

:parse
IF "%~1"=="" GOTO endparse
IF "%~1"=="-a" REM do something
IF "%~1"=="-b" REM do something else
SHIFT
GOTO parse
:endparse
REM ready for action!

This scheme allows you to parse pretty complex command lines without going insane.

Substitution of batch parameters

For parameters that represent file names the shell provides lots of functionality related to working with files that is not accessible in any other way. This functionality is accessed with constructs that begin with %~.

For example, to get the size of the file passed in as an argument use

ECHO %~z1

To get the path of the directory where the batch file was launched from (very useful!) you can use

ECHO %~dp0

You can view the full range of these capabilities by typing CALL /? in the command prompt.