How to pass multiple params in batch? - windows

In my batch file I want to pass multiple parameters to some other application.
Now I do it
app.exe %1 %2
and it can only pass two parameters, but I want to pass all the parameters that are passed to the batch(I would rather not write %1 %2 %3 %4 ...)
Is there any magic way to do it?

There is a magic way! I knew it, but I could not remember it.
its %*

You could use the SHIFT prompt and loop through the arguments. Here is a demonstrative example where you would replace the final ECHO prompt with a prompt to load your application.
#ECHO OFF
SET PARAMS=
:_PARAMS_LOOP
REM There is a trailing space in the next line; it is there for formatting.
SET PARAMS=%PARAMS%%1
ECHO %1
SHIFT
IF NOT "%1"=="" GOTO _PARAMS_LOOP
ECHO %PARAMS%
PAUSE
This may be useful if you need some sort of dynamic parameter counting, or if you want to disallow a certain parameter.

Another way is to use one double quoted parameter. When calling the other application, you just use the %~N device on the command line to remove the quotes.
If some parameters you intend to pass to the application are themselves double-quoted, those quote chars must be repeated twice.
Here's an illustration script that uses the first parameter as the application's name and the second as a combined parameter list to pass to the application:
#ECHO OFF
CALL %1 %~2
Here are examples of calling the script for different cases (pass one parameter or several parameters or quoted parameters).
Pass 1 parameter to the app:
C:\>mybatch.bat app.exe "app_param"
C:\>mybatch.bat app.exe app_param
Pass several parameters:
C:\>mybatch.bat app.exe "app_param1 app_param2 app_param3"
Pass a parameter that includes spaces (and so must be quoted):
C:\>mybatch.bat app.exe """parameter with spaces"""
A combined example: some parameters are with spaces, others aren't:
C:\>mybatch.bat app.exe "param_with_no_spaces ""parameter with spaces"" another_spaceless_param"

Related

Why are strings from text file cut by the FOR loop on passing them to another function?

Prerequisites
I have a file called urls.txt where I store my URLs, e.g.
www.google.de/test1.yaml?at=refs%2Fheads%2Fmaster
www.google.de/test2.yaml?at=refs%2Fheads%2Fmaster
www.google.de/test3.yaml?at=refs%2Fheads%2Fmaster
My goal
Now I want to loop through these URLs and pass them to another function to download them.
:downloader
FOR /F "delims=" %%i IN (urls.txt) DO (call :sub_function %%i)
goto :eof
:sub_function
echo here url is: %~1
Output
The output is that it cuts off the query strings from the URLs and does not pass them completely to the next function.
For example, the output is: www.google.de/test1.yaml?at
What do I miss?
To protect special characters (like the =-sign in your situation, which constitutes a standard token separator just like SPACE, TAB, , and ;), use quotation for the argument, so it is really treated as one.
Then the call command initiates a second %-expansion phase, which is the reason why the %-signs in your argument cause issues (actually the sequence %2 represents the second argument of your script). To circumvent that problem, store the argument string in a variable and ensure that is is going to be expanded during said second %-expansion phase.
Since URLs may also contain the &-symbol, the argument in the sub-function should not become expanded unquoted in order not to misinterpret it as the command concatenation operator.
Here is the corrected code:
:downloader
FOR /F "delims=" %%i IN (urls.txt) DO (
set "ARG=%%i" & call :sub_function "%%ARG%%"
)
goto :eof
:sub_function
echo here url is: "%~1"

Create with pipe a user defined filename batch file

I want to read from stdin a filename for a batch file that I need to create. All in a single line and using pipe.
When I try the cmd is creating the .bat before I put in the name.
set /p filename= | copy NUL %a%.bat
That's not how the pipe works. The pipe takes the output of the previous command, and makes it the input of the next command. Your set /p filename= command doesn't produce any output, so the copy NUL %a%.bat doesn't get any input, but that's irrelevant anyway, because the copy command doesn't take any input anyway. Your copy NUL %a%.bat command creates an empty file called .bat because you haven't defined a variable called a, and so %a% gets expanded to the empty string.
What you want to do requires two commands:
set /p filename=
copy NUL %filename%.bat
As a line in a batch file, use
SET /p "filename=Filename ? "&CALL COPY NUL %%filename%% >nul
If you are entering this at the prompt, reduce %% to %
Note that the >nul suppresses the file copied message.
To complement Klitos Kyriacou's helpful answer:
A pipe is definitely not the right choice, but & and && can in principle be used to execute multiple commands on a single line, so you may be tempted to do the following:
:: !! WRONG
set /p filename="" && copy NUL "%filename%.bat"
The problem is that variable reference %filename% is expanded before execution of the command line begins.[1]
However, if you turn on delayed expansion (via cmd /V, or, inside a batch file with setlocal enabledelayedexpansion (which also makes all variables local)), you can make this work, assuming you use !...! to reference your variables:
:: OK, assuming delayed expansion is on.
set /p filename="" && copy NUL "!filename!.bat"
[1] Magoo's answer works around that problem with a trick: call effectively delays expansion, but that requires that %filename% not be expanded up front, which is why the %% are doubled to result in literal % chars.: %%filename%% is initially expanded to literal %filename%, which is then interpreted by call as a variable reference - by which time the variable already has its value.
Since % chars. cannot be escaped on the command line, a different approach is needed: %filename^% achieves the same as above.

How to pass parameter ending with "!" to another bat file?

I have two bat files and i need to pass three parameter from one bat file to the other. However if the parameter ends in an "!" the parameter is not receieved
caller.bat
impl.bat param1 param2! param3
impl.bat
echo %1
echo %2
echo %3
Expected Result after running caller.bat:
param1
param2!
param3
Actual Result after running caller.bat:
param1
param2
param3
Can anyone help on how i can achieve the actual result?
As the other answers said, it's possible to disable delayed expansion, but it isn't necessary to display an exclamation mark.
It's important that you get the exlamation mark (and other special chaacters) into a variable.
Then you can use it perfectly with delayed expansion
Sample
#echo off
set "param1=%~1"
set "param2=%~2"
setlocal EnableDelayedExpansion
echo Works: !param1! !param2!
echo FAILS: %param1% %param2%
Calling this with
myBatch.bat arg1! "arg2!<>&"
The advantage of delayed expansion is that any content can be handled without side effects, as the expanded content will not be parsed anymore.
Percent expansion will fail in many cases, as the content will be parsed also for special characters
In fact, the explanation mark is received by the destination batch file, but is discarded when the echo command is processed. You can see this if you have echoing turned on. (However, if you use the call command to run the batch file, the explanation mark is not passed to it.)
The explanation mark is only discarded if delayed expansion is enabled. You can correct it by turning delayed expansion off temporarily:
setlocal disabledelayedexpansion
impl.bat param1 param2! param3
You can also work around it by quoting the special character with the caret, though since the argument goes through several levels of processing you have to quote it multiple times:
impl.bat param1 param2^^^^^! param3
or
call impl.bat param1 param2^^^^^^^^^^! param3
This approach may not be reliable, as it depends on what the child is doing with the argument. It is preferable to turn delayed expansion off, although that won't work if the child turns it back on again.
One of the few cases where the solution is to disable delayed expansion. I assume you are enabling it either when launching your cmd.exe, or as a setlocal line in your batch file. Either way, the shortest answer is to stop turning that on - by default cmd parameters do exactly what you want.
If you rely on delayed expansion elsewhere and can't turn it off globally, then you can use setlocal to disable it for a chunk of code.
echo %1
setlocal disabledelayedexpansion
echo %2
endlocal
echo %3
Just note that anywhere you expand a variable with the bang symbol, delayed expansion must be turned off. This includes if you set it to a variable and use that variable later.

Using parameters in batch files at Windows command line

In Windows, how do you access arguments passed when a batch file is run?
For example, let's say I have a program named hello.bat. When I enter hello -a at a Windows command line, how do I let my program know that -a was passed in as an argument?
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.
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)
Use variables i.e. the .BAT variables and called %0 to %9

how to use dos commands to do following

At the following location
\ncsusnasent02.na.jnj.com\its_diq_na_win_dev\PowerCenter\infa_shared\WCPIT_BIO_EDW\SrcFiles\DDDMD\DDD.CLI026.WK0933.DDDMR45.001.head
I have one file
DDD.CLI026.WK0933.DDDMR45.001.head
if i open this file
i get data as following(in a single line)
HEADER0101IMS HEALTHDMD Weekly D DD.CLI026.WK0933.DDDMR45 Centocor DMDDRM45 W2009080210120090831125325ssnyder#us.imshealth.com
TRAIL0101 000000000581 0000000000CKSUM000002236804730
we need to copy 581(it will not be same always it gets updated everyday) from this file
and put it in a variable
you can try the below. It will set the field into the environment variable id:
for /f "tokens=10" %%a IN (%1) do (
SET id=%%a
)
echo %id%
You can pass the full path and file name into the bat as the first argument.
edit:
This simple bat will take the input from the file you specify on the commandline (param %1), it will use the default separators of <space> and <tab> to break the line in your file - defined in the IN set - into a set of tokens. The "tokens=10" param tells the processor to pass the 10th token, which turns out to be your number in question, into the DO block. It is passed in as a param %%a. Within the DO block, I simply assign that value to an environment variable id. After the for command is complete, I echo the value out to the console.
Take a look at the FOR command, specifically the part about the /F parameter.
I'm not certain enough about the structure of that line to even try to write the full command, but you should be able to write it yourself given that information.
Hmm to me it looks more like the guy needs a dos substr... i.e.
#Echo Off
If not %1.==[]. (Cmd /V:On /C Call %0 [] %1 & GoTo :EOF)
Shift
Set MyVariable=HELLOWORLD
Set ASubStr=!MyVariable:~%1!
Echo [!ASubStr!]
So for example save this as test.bat and then call "test.bat 5" and it will echo WORLD
Google DOS Substring and work out how to parse your text variable the way you want it.

Resources