How can I pass arguments to a batch file?
Solution 1
Here's how I did it:
@fake-command /u %1 /p %2
Here's what the command looks like:
test.cmd admin P@55w0rd > test-log.txt
The %1
applies to the first parameter the %2
(and here's the tricky part) applies to the second. You can have up to 9 parameters passed in this way.
Solution 2
Another useful tip is to use %*
to mean "all". For example:
echo off
set arg1=%1
set arg2=%2
shift
shift
fake-command /u %arg1% /p %arg2% %*
When you run:
test-command admin password foo bar
the above batch file will run:
fake-command /u admin /p password admin password foo bar
I may have the syntax slightly wrong, but this is the general idea.
Solution 3
If you want to intelligently handle missing parameters you can do something like:
IF %1.==. GOTO No1
IF %2.==. GOTO No2
... do stuff...
GOTO End1
:No1
ECHO No param 1
GOTO End1
:No2
ECHO No param 2
GOTO End1
:End1
Solution 4
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 echo on
and expand the %1 after a rem
statement (works also with %2 .. %*
).
So even "&"&
could be echoed without producing an error, as it is remarked.
But to be able to redirect the output of the echo on
, you need the two for-loops.
The extra characters * #
are used to be safe against contents like /?
(would show the help for REM
).
Or a caret ^ at the line end could work as a multiline character, even in after a rem
.
Then reading the rem parameter 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 param1
, you got it.
And to use param1
in a safe way, enable the delayed expansion.
Solution 5
Yep, and just don't forget to use variables like %%1
when using if
and for
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.
Keng
Personal Achievables: Medical Note: I now have irreversible damage to my kidneys and liver after having used this site.
Updated on July 24, 2022Comments
-
Keng almost 2 years
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 P@55w0rd > test-log.txt
-
Denilson Sá Maia over 14 yearsPlease note that %* does not work everywhere! For instance, it does not work with DOSBox 0.73 (maybe this is a bug that should be reported).
-
Kef Schecter over 12 yearsIt's not a bug because %* never worked in MS-DOS or Win9x in the first place.
-
Royi Namir over 11 years%% is only for
if
andfor
? -
Steve Midgley over 11 yearsIt's worse than that - %% is used to prefix variables and command line parameters inside batch files. But when you use these commands from the command line, you use only % to prefix. Example: inside batch:
for %%d in (*) do echo %%d
from command line:for %d in (*) do echo %d
-
ruffin over 9 yearsIf you're as dumb as me, your mind was looking for
echo %1 %2
and was thrown off by the non cut-and-pasteable simplest case with a@
and afake-command
with params, thinking we'd getfake-command.bat
's contents later (in which case, the overcomplicatedfake-command.bat
might haveecho %2 %4
to ignore the param names). Wrong, doofus. TL;DR: Don't be as dumb as me. 1.echo echo %1 %2 > test.bat
2.test word1 word2
. 3. Profit. -
NathanAldenSr about 8 yearsI think
shift
"pops" the argument from the list. The assumption by OP was that%*
would only output the remaining arguments, but it doesn't work that way, as @Joey said. -
Paint_Ninja almost 8 yearsYou can close the cmd window after the process has closed using the following command in a batch script:
start /wait java %~n1
-
Jono_2007 almost 8 yearsBeen looking at using this method as I would like to pass arguments into a batch file in this manner. However I notice that after the variables are set, even after exiting the batch file the parameters are still set in the cmd if accessed and the batch has ended, they are not restored to their previous state. Should this method handle that situation?
-
icc97 over 7 years@SteveMidgley I upvoted your comment probably a year or so ago. I then promptly forgot about it and just today I was trying and staring confusingly at my for loop in the command line and wondering why it farted and did nothing else. So here's another virtual upvote from me. I'll be back in another year or so when I hit the same issue again.
-
Chris over 7 yearsWhat's the significance of dot/period in these equality operations?
-
Carl over 7 yearsBasically if %1 is empty, this will end up being IF . == . and so the GOTO will happen. We use x here so: IF x%1 == x -> IF x==x -> true
-
Kevin Edwards about 7 yearsfor /F "tokens=*" %%a in ('echo %*') do set "all_args=%%a"
-
jeb about 7 years@KevinEdwards Then try it with one
&
, your solution works only with simple content -
jeb about 7 years@KevinEdwards I tested it,
test.bat ^&
and it fails. Onlytest.bat "&"
works, but that wasn't my point. You can't use%*
,%1
in a safe way without the REM technic -
Kevin Edwards about 7 yearsAh, yes, a caret doesn't escape it properly. You need quotes, which is feasible for all the use cases I've come across. I just wanted to pass it along. Thanks for testing it! Cheers :)
-
Explorer09 about 7 yearsI have a concern about this method (echo-on-and-rem-piped-to-a-file trick): Although batch and cmd.exe don't allow newlines in command arguments, but for shells that allow it when calling the script, the trick breaks. And don't laugh, because PowerShell allow newlines in arguments. Using low-level CreateProcess() function is also possible to make a newline and break it.
-
jeb about 7 years@Explorer09 Batch and also cmd.exe allowes both newlines in arguments, but it's tricky. The
echo-on-and-rem-redirect-to-a-file trick
can also fetch multiline arguments, but that isn't bullet proof, see SO:...multi line text as argument... -
Explorer09 about 7 years@jeb The SO answer you mentioned does allow multi-line argument parsing, but doesn't protect against command injection from line 2 and onward. I fear there will be no true bullet-proof solution until there's an extension syntax (e.g.
!1!
!2!
or!!1
!!2
) that can truly delay-expand the arguments. -
jwdonahue over 6 yearsOver complicated and mostly not directly related the OP's question.
-
jwdonahue over 6 yearsWe usually reserve the digits for command line processing and the double percent only applies to the for statement as far as I know.
@for %%2 in (testing) do @echo %%2 %1
in a batch file, producestesting 1
when it is called with 1 (test 1
). -
jwdonahue over 6 yearsTrue enough, but it barely touches the subject matter.
-
jwdonahue over 6 yearsOn topic and better than some of the rest of the answers on this thread.
-
jwdonahue over 6 yearsAdvising the public to put random script files in the system32 directory is irresponsible. This answer really doesn't scratch the surface of the topic of this thread.
-
jwdonahue over 6 yearsThis answer is wrong. It actually results in
fake-command /u admin /p password admin password foo bar
. This was pointed out by @Joey many years ago. -
Adriano G. V. Esposito over 6 yearsYou should aks for what is the value of a "unprovided argument"? Againts what you should check an "unprovided argument"? Then, if you don't have an answer, you should use a trick like the one of the dots. Remember that, like stated here ss64.com/nt/if.html "You can in fact use almost any character for this a '~' or curly brackets, { } or even the number 4, but square brackets tend to be chosen because they don't have any special meaning."
-
Fotios Basagiannis over 5 yearsThe two shifts are pointless in this case. AFTER them %1 would become foo and %2 would become bar but this is not used in any way and %* is not affected by the shift command
-
Max over 4 yearsExtended it to support flag args (without values). Sorry for lack of formatting but it doesn't work in comments :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 ) else ( if not "%__var%"=="" ( endlocal & set %__var:~1%=1 ) )
-
jeb over 4 yearsBut fails with many different arguments, like
test.bat *.txt
,test.bat cat^&dog
orTest.bat /?
-
jeb over 4 yearsThe answer is wrong.
%%1
doesn't access a command line argument, and it's also wrong for theIF
command. Only theFOR
command (in batch files) requires double percents, but even then%%1
would define a FOR parameter and doesn't access arguments -
jeb over 4 years@jwdonahue Yes, it's complicated (but not over complicated). But especially for passwords it could be necessary, at least some of my passwords contain ampersands
&
and also quotes"
-
ruffin almost 4 yearsFive years later, I'm back reading my comment w/ confusion. Seem to have meant "to create a .bat with two parameters, literally type
echo echo %1 %2 > test.bat
. The test.bat file will haveecho %1 %2
in it (you could've also saved it from a text editor). Now typetest word1 word2
to call & see the parameters worked.word1 word2
will be echoed to the command line. (echo %2 %4
would've ignored/u
and/p
so you could've calledtest /u word1 /p word2
to get the same result).@
before a cmd in a bat file means the cmd isn't repeated. -
NTDLS almost 3 yearsGreat answer. Concise and easy to follow. 🔥
-
Alan about 2 yearsI know, a long time ago. But thank you! Simple is best, we can figure out the rest. Huh, a poem.
-
Love and peace - Joe Codeswell about 2 years"Simple is best, we can figure out the rest"! Words to live by. Thanks, Alan.
-
Flo about 2 yearsWhat a piece of beauty! For future readers, I only want to highlight that the
-f
flag is not actually included in the parse-section yet. Just a heads up! -
kodybrown about 2 yearsI accepted your edit @Flo. Thanks!
-
Sayan Dasgupta about 2 yearswhat does fake-command do or what does it mean ?
-
DennisVM-D2i about 2 yearsJoey is right - shift does not affect '%*'.
-
DennisVM-D2i about 2 yearsYou might want some quote handling/protection too, e.g.: SetLocal Set dbName=%1 Rem dbName If Not Defined dbName Goto SyntaxErr REM Remove all (/any) the quotes Set dbName=%dbName:"=% If "%dbName%" == "" Goto SyntaxErr