Is there a convenient way to do this?
for /F "tokens=1,*" %%a in ("%*") do (
set arg1st=%%a
set argrest=%%b
)
echo %%1: %arg1st%
echo rest: %argrest%
Nice, but breakable (what wouldn't be?)
C:\_D\TEST>HARLAN.CMD "1 "
The system cannot find the file
<>.
%1: "1
rest: "
The problem lies, not surprisingly, with quoted arguments.
Another, more complicated taking, but copping out using %~1
@echo off & setlocal enableextensions
rem enabledelayedexpansion
echo +----------------------------------------------------+
echo ^| CMD2DEMO.CMD Another selection of CMD syntax tips ^|
echo ^| By Prof. Timo Salmi http://lipas.uwasa.fi/~ts/ ^|
echo ^| Last modified Fri 29-Feb-2008 ^|
echo +----------------------------------------------------+
echo.
::
rem One frequent set of questions pertains to getting the first, rest,
rem and/or the last item in the arguments (replaceable parameters)
rem of a script call. Likewise, it is often asked how the parts of a
rem file path can be parsed. This generic demo does both (without
rem resorting to the special file-related FOR arguments handling).
::
rem This script file will part of the following collection:
rem ftp://garbo.uwasa.fi/pc/link/tscmd.zip
rem Useful NT/2000/XP script tricks and tips, T.Salmi
::
:: Get the string to be parsed, or use a demo default
set MyArguments=%~1
if "%~1"=="" set MyArguments=d:\folder 1\folder 2\folder 3
echo MyArguments=%MyArguments%
echo.
::
:: Choose the delims
echo %MyArguments%|find "\">nul
if %errorlevel% EQU 0 (set delims_=\) else (set delims_= )
::
:: Get the first part and the rest of a variable
for /f "tokens=1* delims=%delims_%" %%a in ("%MyArguments%") do (
set first_=%%a
set rest_=%%b
)
echo first_=%first_%
echo rest_ =%rest_%
::
:: Get the last part of a variable
set rest_=%MyArguments%
:_loop
for /f "tokens=1,* delims=%delims_%" %%a in ("%rest_%") do (
set rest_=%%b
set last_=%%a
if defined rest_ goto _loop
)
echo last_=%last_%
::
endlocal & goto :EOF
Example outputs
C:\_D\BAS>C:\_F\CMD\CMD2DEMO.CMD
+----------------------------------------------------+
| CMD2DEMO.CMD Another selection of CMD syntax tips |
| By Prof. Timo Salmi http://lipas.uwasa.fi/~ts/ |
| Last modified Fri 29-Feb-2008 |
+----------------------------------------------------+
MyArguments=d:\folder 1\folder 2\folder 3
first_=d:
rest_ =folder 1\folder 2\folder 3
last_=folder 3
C:\_D\BAS>C:\_F\CMD\CMD2DEMO.CMD "1 2 Whatever"
+----------------------------------------------------+
| CMD2DEMO.CMD Another selection of CMD syntax tips |
| By Prof. Timo Salmi http://lipas.uwasa.fi/~ts/ |
| Last modified Fri 29-Feb-2008 |
+----------------------------------------------------+
MyArguments=1 2 Whatever
first_=1
rest_ =2 Whatever
last_=Whatever
All the best, Timo
--
Prof. Timo Salmi ftp & http://garbo.uwasa.fi/ archives 193.166.120.5
Department of Accounting and Business Finance ; University of Vaasa
mailto:t...@uwasa.fi <http://www.uwasa.fi/~ts/> ; FI-65101, Finland
Timo's Turbo Pascal FAQ from ftp://garbo.uwasa.fi/pc/link/tsfaqp.zip
Thanks to the both of you. Is there a way to create a more generic
function - one that could accept an integer parameter N and return the
arguments N+? Such a function could be dropped into different batch
scripts where there are a differing numbers of required arguments and
where you'd want to pass the rest along.
You might first wish to take a look in the related tricks in
40) How do I get the number of arguments given to a script?
207709 Feb 23 2008 ftp://garbo.uwasa.fi/pc/link/tscmd.zip
Http link format http://garbo.uwasa.fi/pub/pc/link/tscmd.zip
tscmd.zip Useful NT/2000/XP script tricks and tips, T.Salmi
All the best, Timo
--
Prof. Timo Salmi ftp & http://garbo.uwasa.fi/ archives 193.166.120.5
Department of Accounting and Business Finance ; University of Vaasa
mailto:t...@uwasa.fi <http://www.uwasa.fi/~ts/> ; FI-65101, Finland
Timo's FAQ materials at http://www.uwasa.fi/~ts/http/tsfaq.html
Which has its own problems with comma or semicolons rather than
whitespace as argument separators.
> type simple.bat
@echo off & setlocal enableextensions
echo %%*: %*
set n=0
:LOOP
if "%~1" == "" goto :EOF
set /A n+=1
echo %%%n%: %1
shift
goto LOOP
> simple 1,2,3,4,5
%*: 1,2,3,4,5
%1: 1
%2: 2
%3: 3
%4: 4
%5: 5
> simple 1;2;3;4;5
%*: 1;2;3;4;5
%1: 1
%2: 2
%3: 3
%4: 4
%5: 5
> cmd2demo 1,2,3,4,5
+----------------------------------------------------+
| CMD2DEMO.CMD Another selection of CMD syntax tips |
| By Prof. Timo Salmi http://lipas.uwasa.fi/~ts/ |
| Last modified Fri 29-Feb-2008 |
+----------------------------------------------------+
MyArguments=1
first_=1
rest_ =
last_=1
> cmd2demo "1,2,3,4,5"
+----------------------------------------------------+
| CMD2DEMO.CMD Another selection of CMD syntax tips |
| By Prof. Timo Salmi http://lipas.uwasa.fi/~ts/ |
| Last modified Fri 29-Feb-2008 |
+----------------------------------------------------+
MyArguments=1,2,3,4,5
first_=1,2,3,4,5
rest_ =
last_=1,2,3,4,5
The devil is in the details, ain't it?
As far as I can see this would be a time for an expedient use of
VBScript, which is almost certainly available as cscript.exe on the
OP's machine.
@echo off & setlocal enableextensions
echo %%*: %*
if "%~2" == "" goto :EOF
set a1=%1
set a1="%a1:"=""%"
set a2=%2
set a2="%a2:"=""%"
set ar=%*
set ar="%ar:"=""%"
> %0.vbs echo ^
wscript.stdout.writeline mid(%ar%, instr(len(%a1%) + 1, %ar%, %a2%))
for /F "delims=" %%a in ('cscript //nologo %0.vbs') do set ar=%%a
echo %%1: %1
echo rest: %ar%
del %0.vbs
I'm sure this also breaks for some nastier command line arguments, but
it handles simple quoted arguments and all argument separators.
With regard to the OP's follow-up question, if the remaining command
line arguments are what's needed rather than the EXACT remaining
command line, e.g., given the arguments
first second third fourth fifth sixth,foo;bar
it'd be OK to represent the command line tail beginning with the 3rd
argument as
third fourth fifth sixth foo bar
then VBScript would again be expedient.
set n=3 & rem starting point for command line tail
> %0.vbs echo for n = %n% to wscript.arguments.count
>> %0.vbs echo a = a & " " & wscript.arguments(n - 1)
>> %0.vbs echo next
>> %0.vbs echo wscript.stdout.writeline mid(a, 2)
for /F "delims=" %%a in ('cscript //nologo %0.vbs') do set ar=%%a
del %0.vbs
> Timo Salmi <t...@uwasa.fi> wrote...
>> Another, more complicated taking, but copping out using %~1
> Which has its own problems with comma or semicolons rather than
> whitespace as argument separators.
Which, fortunately, is easily remedied by elaborating the delims test.
Or, of course, more usually by fixing in advance what the delims are.
::
:: Choose the delims
(set delims_= )
echo %MyArguments%|find "\">nul
if %errorlevel% EQU 0 set delims_=\
echo %MyArguments%|find ",">nul
if %errorlevel% EQU 0 set delims_=,%delims_%
echo %MyArguments%|find ";">nul
if %errorlevel% EQU 0 set delims_=;%delims_%
::
Incidentally, note that it is imperative to have e.g. ,%delims_% instead
of %delims_%,
> @echo off & setlocal enableextensions
> echo %%*: %*
> set n=0
> :LOOP
> if "%~1" == "" goto :EOF
> set /A n+=1
> echo %%%n%: %1
> shift
> goto LOOP
In fact, a shift solution is what I suggest since ages in my FAQ item
40. It makes available argc and argv[i] (i=1,...,argc) which renders
the op-asked variations possible to solve in a rather generic manner.
Quoting from #40
The output might be e.g.
C:\_D\TEST>cmdfaq a b c "d e"
argc=4
argv[1]=a
argv[2]=b
argv[3]=c
argv[4]=d e
> The devil is in the details, ain't it?
Yes. Thanks for the examples.
> As far as I can see this would be a time for an expedient use of
> VBScript, which is almost certainly available as cscript.exe on the
> OP's machine.
VBS has more power. And having different options always is good.
Obviously could also be done with gawk. This time I went for a
non-third-party, non-VBS option.
@echo off & setlocal enableextensions enabledelayedexpansion
set n=0
if not "%~1"=="" (set p[1]=%~1&set n=1)
if not "%~2"=="" (set p[2]=%~2&set n=2)
if not "%~3"=="" (set p[3]=%~3&set n=3)
if not "%~4"=="" (set p[4]=%~4&set n=4)
if not "%~5"=="" (set p[5]=%~5&set n=5)
if not "%~6"=="" (set p[6]=%~6&set n=6)
if not "%~7"=="" (set p[7]=%~7&set n=7)
if not "%~8"=="" (set p[8]=%~8&set n=8)
if not "%~9"=="" (set p[9]=%~9&set n=9)
echo n=%n%
for /L %%i in (1,1,9) do echo p[%%i]=!p[%%i]!
for /L %%i in (2,1,9) do if defined p[%%i] set rest_=!rest_! !p[%%i]!
echo rest_=%rest_%
endlocal & goto :EOF
C:\_D\BAS>cmdfaq 1 2;3,4 "Hello world"
n=5
p[1]=1
p[2]=2
p[3]=3
p[4]=4
p[5]=Hello world
p[6]=
p[7]=
p[8]=
p[9]=
rest_= 2 3 4 Hello world
All the best, Timo
--
Prof. Timo Salmi ftp & http://garbo.uwasa.fi/ archives 193.166.120.5
Department of Accounting and Business Finance ; University of Vaasa
mailto:t...@uwasa.fi <http://www.uwasa.fi/~ts/> ; FI-65101, Finland
Useful script files and tricks ftp://garbo.uwasa.fi/pc/link/tscmd.zip
>One, ugly option
This is a little nicer Timo. It handles ! characters and retains quoted
command line entries.
@echo off
for %%a in (%*) do set /a n=n+1&(call set p[%%n%%]=%%a)
echo Number of entries=%n%
for /L %%a in (1,1,100) do (
if defined p[%%a] call echo p[%%a]=%%p[%%a]%%)
for /L %%a in (2,1,100) do if defined p[%%a] (
call set rest_=%%rest_%% %%p[%%a]%%)
echo rest_=%rest_%
===[screen capture]===
Number of entries=5
p[1]=1
p[2]=2
p[3]=3
p[4]="Hello World"
p[5]="a & b"
rest_= 2 3 "Hello World" "a & b"
===[screen capture]===
Thanks! I forgot about the call-trick to replace delayed expansion. I'll
use something like this directly drawn from your ideas
@echo off & setlocal enableextensions disabledelayedexpansion
set n=0
for %%a in (%*) do (set /a n+=1)&(call set p[%%n%%]=%%a)
::
echo n=%n%
for /L %%i in (1,1,9) do if defined p[%%i] call echo p[%%i]=%%p[%%i]%%
for /L %%i in (2,1,9) do if defined p[%%i] call set rest_=%%rest_%%
%%p[%%i]%%
if defined rest_ set rest_=%rest_:~1%
echo rest_=%rest_%
endlocal & goto :EOF
And, indeed
C:\_D\TEST>cmdfaq 1 2 3 "Hello World" "a & b"
n=5
p[1]=1
p[2]=2
p[3]=3
p[4]="Hello World"
p[5]="a & b"
rest_=2 3 "Hello World" "a & b"