1

I have found the following command to get all but the first two parameters:
for /f "tokens=2,*" %%a in ("%*") do set AFTER_SECOND=%%b
My problem is that I have to use "^" and "," in my command, but batch sees them as delimeters and doesn't pass them.
I tried to pass this:"2,5^^3", but than it won't pass the ","
Thank you for help!

simgo
  • 31
  • 5

1 Answers1

1

Open a command prompt window and run cmd /? to get output the help for Windows command processor. The last help page explains in last paragraph when especially a file name (or any other argument string) must be enclosed in double quotes, i.e. argument string contains a space or one of these characters &()[]{}^=;!'+,`~<|>. Please note that <|> are not valid in file/folder names, but are possible in general argument strings.

Next run in command prompt window call /?. The output help explains how batch file arguments can be referenced including the all passed arguments reference %* which references all argument strings exactly as passed to the batch file with exception of argument 0 which is the batch file name exactly as typed by user on running the batch file from within a command prompt window.

Now let us look on a very simple batch file which is named Test.bat:

@echo off
echo %0 %*
for /F "tokens=3*" %%I in ("%*") do echo FOR: %%I %%J
pause

Test.bat is executed from within a command prompt window with:

Test 1 2 3 4 5 6

The second command line outputs exactly the line as written above.

But what does FOR do in this case?

Running for /? in command prompt window outputs the help of command FOR and explains option /F as well as meaning of tokens=3*.

FOR expects here a string enclosed in double quotes like "..." with spaces/tabs not containing double quotes. This string should be split up into substrings using spaces/tabs on not starting with default end of line (eol) character ; whereby third space/tab delimited substring should be assigned to specified loop variable I and rest of string after spaces/tabs after third substring should be assigned to next variable according to ASCII table which would be J in this case.

So the output is as expected:

Test 1 2 3 4 5 6
FOR: 3 4 5 6

The FOR command line outputs noting on running:

Test ;1 2 3 4 5 6

The reason is default eol=; and the semicolon at beginning of the string processed by FOR. Only the second command line outputs the used command line for running the batch file. So output is just: Test ;1 2 3 4 5 6

Next we run Test.bat with:

Test 1 2 3

The output is:

Test 1 2 3
FOR: 3 

There is a trailing space on line output by FOR.

But what happens on running the batch file with following command line?

Test.bat "First argument" "1, 2, 3 in second argument" "^ caret in third argument" "and so on"

The second command line outputs this line. But FOR has to process:

""First argument" "1, 2, 3 in second argument" "^ caret in third argument" "and so on""

FOR fails completely to interpret this string as expected by you containing multiple double quotes, i.e. in real multiple argument strings in set to process.

So how to get all arguments with ignoring the first two argument strings into an environment variable separated with spaces to later process this string concatenated from multiple batch file argument strings?

One solution is using the command SHIFT in a loop together with command SET.

@echo off
setlocal EnableExtensions DisableDelayedExpansion
set "AllArguments="

:ArgLoop
set "Argument=%~3"
if defined Argument (
    set "AllArguments=%AllArguments% %Argument%"
    shift /3
    goto ArgLoop
)
rem Is there no more argument or is the argument string just empty?
set "Argument=%3"
if defined Argument shift /3 & goto ArgLoop

rem All argument strings processed, remove first space from the concatenated string.
if defined AllArguments set "AllArguments=%AllArguments:~1%"

cls
echo The batch file was called with:
echo/
echo %0 %*
echo/
echo All arguments starting from third argument are:
echo/
echo "%AllArguments%"
echo/
endlocal
pause

This batch file also named Test.bat is for example executed with:

Test.bat "First argument" SecondArgument "^ caret in third argument" "" "Fifth argument!" "1,2,3 | 233 < 234 > 235" "& more arguments" "without or" with,double;quotes=whereby "by mistake last argument has a double" quote at end"

That is really an awful arguments list for processing it with a batch file.

  • There is escape character ^ included in third argument string interpreted as literal character inside a double quoted argument string.
  • The fourth argument string is an empty argument string.
  • There is ! in fifth argument string which is interpreted as begin/end of a delayed environment variable reference if delayed expansion would be enabled in batch file even on being inside a double quoted argument string.
  • Next argument string contains argument separator , and the redirection operators |, < and > interpreted as literal characters because of being in a double quoted argument string.
  • Operator & is included also which has multiple meanings like on redirection with 2>&1 or for multiple commands in one command line, but is interpreted here as literal character because of being also inside a double quoted string.
  • There are ,, ; and = not inside a double quoted argument string and therefore interpreted as argument separators by cmd.exe.
  • And last but not least the last argument ends with ", but does not start with ".

The output of this command line with above batch file is with 80 columns per line:

The batch file was called with:

Test.bat "First argument" SecondArgument "^ caret in third argument" "" "Fifth a
rgument!" "1,2,3 | 233 < 234 > 235" "& more arguments" "without or" with,double;
quotes=whereby "by mistake last argument has a double" quote at end"

All arguments starting from third argument are:

"^ caret in third argument Fifth argument! 1,2,3 | 233 < 234 > 235 & more argume
nts without or with double quotes whereby by mistake last argument has a double
quote at end""

Looks good, isn't it.

By the way: It would be no good idea to output value of %AllArguments% without using double quotes in this case because of all those characters with special meanings for cmd.exe outside a double quoted argument string. But it is possible to replace echo "%AllArguments%" by setlocal EnableDelayedExpansion & echo !AllArguments!& endlocal to output the string value of environment variable AllArguments without double quotes with using delayed expansion. See also How does the Windows Command Interpreter (CMD.EXE) parse scripts?

Note 1: Command SHIFT does not modify the all passed arguments string referenced by %* as this batch file demonstrates. It modifies only the numbered argument references as used by this batch file to process always third argument in a loop until there is really no more argument.

Note 2: Maximum size of an environment variable is 8192 bytes which includes the bytes for variable name, one equal sign (separator between name and value) and a string terminating null byte. In other words maximum length assigned to an environment variable is: 8192 - 2 - length of variable name

For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.

  • call /?
  • cls /?
  • echo /?
  • endlocal /?
  • goto /?
  • if /?
  • rem /?
  • set /?
  • setlocal /?
  • shift /?

PS: I am quite sure this code is still not handling all combinations of arguments correct, but it should work in nearly all use cases.

Mofi
  • 46,139
  • 17
  • 80
  • 143