with - windows cmd parameters
How can I pass arguments to a batch file? (12)
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:
test.cmd admin [email protected] > test-log.txt
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
>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"
@::!/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
Accessing batch parameters can be simple with %1, %2, ... %9 or also %*,
but only if the content is simple.
There is no simple way for complex contents like
, as it's not possible to access %1 without producing an error.
set var=%1 set "var=%1" set var=%~1 set "var=%~1"
The lines expand to
set var="&"& set "var="&"&" set var="&"& set "var="&"&"
And each line fails, as one of the
is outside of the quotes.
It can be solved with reading from a temporary file a remarked version of the parameter.
@echo off SETLOCAL DisableDelayedExpansion SETLOCAL for %%a in (1) do ( set "prompt=" echo on for %%b in (1) do rem * #%1# @echo off ) > param.txt ENDLOCAL for /F "delims=" %%L in (param.txt) do ( set "param1=%%L" ) SETLOCAL EnableDelayedExpansion set "param1=!param1:*#=!" set "param1=!param1:~0,-2!" echo %%1 is '!param1!'
The trick is to enable
and expand the %1 after a
statement (works also with
%2 .. %*
could be echoed without producing an error, as it is remarked.
But to be able to redirect the output of the
, you need the two for-loops.
The extra characters
are used to be safe against contents like
(would show the help for
Or a caret ^ at the line end could work as a multiline character, even in after a
Then reading the
output from the file, but carefully.
The FOR /F should work with delayed expansion off, else contents with "!" would be destroyed.
After removing the extra characters in
, you got it.
And to use
in a safe way, enable the delayed expansion.
Here's how I did it:
@fake-command /u %1 /p %2
Here's what the command looks like:
test.cmd admin [email protected] > test-log.txt
applies to the first parameter the
(and here's the tricky part) applies to the second. You can have up to 9 parameters passed in this way.
I wrote a simple read_params script that can be called as a function (or external
) and will put all variables into the current environment. It won't modify the original parameters because the function is being
ed with a copy of the original parameters.
For example, given the following command:
myscript.bat some -random=43 extra -greeting="hello world" fluff
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
Cannot load arguments with no value such as
-force. You could use
-force=truebut 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.
- No longer requires delayed expansion
Now works with other command line arguments by looking for
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
. It requires an initial command. It has an optional parameter
which takes an
value (which cannot be another parameter, of course); if the value is missing it defaults to
. It also has an optional parameter
which takes a
value. Lastly it can take a flag
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
SETLOCALso 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.
%~1to remove quotes.
IF "%ARG%" == ""and not
IF [%ARG%] == because
]don't play will at all with values ending in a space.
Even if you
IFblock, the current args such as
%~1don't get updated because they are determined when the
IFis parsed. You could use
IFblock, but it would be confusing because you had a
SHIFT. You could put the
SHIFTat the end of the block for clarity, but that might get lost and/or confuse people as well. So "capturing"
%~1outside 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
SHIFTwhen 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
--fooparameter was present and also that the
%FOO%value was missing.
ECHO Missing bar value. 1>&2sends the error message to stderr.
Want a blank line in a Windows batch file? You gotta use
ECHO:or one of the variations.
Make a new batch file (example: openclass.bat) and write this line in the file:
Then place the batch file in, let's say, the system32 folder, go to your Java class file, right click, Properties, Open with..., then find your batch file, select it and that's that...
It works for me.
PS: I can't find a way to close the cmd window when I close the Java class. For now...
Simple solution(even though question is old)
echo off echo "Batch started" set arg1=%1 echo "arg1 is %arg1%" echo on pause
call "C:\Temp\Test1.bat" pass123
YourLocalPath>call "C:\Temp\test.bat" pass123 YourLocalPath>echo off "Batch started" "arg1 is pass123" YourLocalPath>pause Press any key to continue . . .
Where YourLocalPath is current directory path.
To keep things simple store the command param in variable and use variable for comparison.
Its not just simple to write but its simple to maintain as well so if later some other person or you read your script after long period of time, it will be easy to understand and maintain.
To write code inline : see other answers.
To refer to a set variable in command line you would need to use
so for example:
set a=100 echo %a% rem output = 100
Note: This works for Windows 7 pro.
Yep, and just don't forget to use variables like
and the gang.
If you forget the double
, then you will be substituting in (possibly null) command line arguments and you will receive some pretty confusing error messages.
@ECHO OFF :Loop IF "%1"=="" GOTO Continue SHIFT GOTO Loop :Continue
will cause problems if
is enclosed in quotes itself.
In that case, use
or, in NT 4 (SP6) and later only,
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.