[ACCEPTED]-How to make SHIFT work with %* in batch files-windows-xp

Accepted answer
Score: 21

Wouldn't it be wonderful if CMD.EXE worked 11 that way! Unfortunately there is not a good 10 syntax that will do what you want. The best 9 you can do is parse the command line yourself 8 and build a new argument list.

Something 7 like this can work.

@echo off
setlocal
echo %*
shift
set "args="
:parse
if "%~1" neq "" (
  set args=%args% %1
  shift
  goto :parse
)
if defined args set args=%args:~1%
echo(%args%

But the above has problems 6 if an argument contains special characters 5 like ^, &, >, <, | that were escaped instead 4 of quoted.

Argument handling is one of many 3 weak aspects of Windows batch programming. For 2 just about every solution, there exists 1 an exception that causes problems.

Score: 4

That´s easy:

setlocal ENABLEDELAYEDEXPANSION
  set "_args=%*"
  set "_args=!_args:*%1 =!"

  echo/%_args%
endlocal

Same thing with comments:

:: Enable use of ! operator for variables (! works as % after % has been processed)
setlocal ENABLEDELAYEDEXPANSION
  set "_args=%*"
  :: Remove %1 from %*
  set "_args=!_args:*%1 =!"
  :: The %_args% must be used here, before 'endlocal', as it is a local variable
  echo/%_args%
endlocal

Example:

lets say %* is "1 2 3 4":

setlocal ENABLEDELAYEDEXPANSION
  set "_args=%*"             --> _args=1 2 3 4
  set "_args=!_args:*%1 =!"  --> _args=2 3 4

  echo/%_args%
endlocal

Remarks:

  • Does not work if any argument contains the ! or & char
  • Any extra spaces in between arguments will NOT be removed
  • %_args% must be used before endlocal, because it is a local variable
  • If no arguments entered, %_args% returns * =
  • Does not shift if only 1 argument entered

0

Score: 3

Don't think there's a simple way to do so. You 2 could try playing with the following workaround 1 instead:

@ECHO OFF
>tmp ECHO(%*
SET /P t=<tmp
SETLOCAL EnableDelayedExpansion
IF DEFINED t SET "t=!t:%1 =!"
ECHO(!t!

Example:

test.bat 1 2 3=4

Output:

2 3=4
Score: 1

Another easy way of doing this is:

set "_args=%*"
set "_args=%_args:* =%"

echo/%_args%

Remarks:

  • Does not work if first argument (%1) is 'quoted' or "double quoted"
  • Does not work if any argument contains the & char
  • Any extra spaces in between arguments will NOT be removed

0

Score: 1

I had to do this recently and came up with 6 this:

setlocal EnableDelayedExpansion

rem Number of arguments to skip
set skip=1

for %%a in (%*) do (
  if not !position! lss !skip! (
    echo Argument: '%%a'
  ) else (
    set /a "position=!position!+1"
  )
)

endlocal

It uses loop to skip over N first arguments. Can 5 be used to execute some command per argument 4 or build new argument list:

setlocal EnableDelayedExpansion

rem Number of arguments to skip
set skip=1

for %%a in (%*) do (
  if not !position! lss !skip! (
    set args=!args! %%a
  ) else (
    set /a "position=!position!+1"
  )
)

echo %args%

endlocal

Please note that 3 the code above will add leading space to 2 the new arguments. It can be removed like 1 this:

Score: 1

Yet another obnoxious shortcoming of DOS/Windows 12 batch programming...

Not sure if this is 11 actually better than some of the other answers 10 here but thought I'd share something that 9 seems to be working for me. This solution 8 uses FOR loops rather than goto, and is 7 contained in a reusable batch script.

Separate 6 batch script, "shiftn.bat":

@echo off
setlocal EnableDelayedExpansion
set SHIFTN=%1
FOR %%i IN (%*) DO IF !SHIFTN! GEQ 0 ( set /a SHIFTN=!SHIFTN! - 1 ) ELSE ( set SHIFTEDARGS=!SHIFTEDARGS! %%i ) 
IF "%SHIFTEDARGS%" NEQ "" echo %SHIFTEDARGS:~1%

How to use shiftn.bat 5 in another batch script; in this example 4 getting all arguments following the first 3 (skipped) arg:

FOR /f "usebackq delims=" %%i IN (`call shiftn.bat 1 %*`) DO set SHIFTEDARGS=%%i 

Perhaps someone else can make 2 use of some aspects of this solution (or 1 offer suggestions for improvement).

Score: 0

Resume of all and fix all problems:

set Args=%1
:Parse
shift
set First=%1
if not defined First goto :EndParse
  set Args=%Args% %First%
  goto :Parse
:EndParse

Unsupport 1 spaces between arguments: 1 2 3 4 will be 1 2 3 4

More Related questions