batch parameters: everything after %1

37,815

Solution 1

I am not sure if there is a direct command but you can always use a simple loop and shift to get the result in a variable. Something like:

@echo off
set RESTVAR=
shift
:loop1
if "%1"=="" goto after_loop
set RESTVAR=%RESTVAR% %1
shift
goto loop1

:after_loop
echo %RESTVAR%

Let me know if it helps!

Solution 2

There is a shorter solution (one-liner) utilizing the tokenization capabilities of for loops:

:: all_but_first.bat
echo all: %*
for /f "tokens=1,* delims= " %%a in ("%*") do set ALL_BUT_FIRST=%%b
echo all but first: %ALL_BUT_FIRST%

output:

> all_but_first.bat foo bar baz
all: foo bar baz
all but first: bar baz

Footnote: Yes, this solution has issues. Same as pretty much anything written with batch files. It's 2021. Use Powershell or literally any other actual scripting language.

Solution 3

The following will work for args with ", =, ' '. Based on Dmitry Sokolov answer. Fixed issue when second arg is the same as first arg.

@echo off
echo %*
set _tail=%*
call set _tail=%%_tail:*%1=%%
echo %_tail%

Solution 4

The following will work for args with ", =, ' ' (as compared to @MaxTruxa answer)

echo %*
set _all=%*
call set _tail=%%_all:*%2=%%
set _tail=%2%_tail%
echo %_tail%

Test

> get_tail.cmd "first 1" --flag="other options" --verbose
"first 1" --flag="other options" --verbose
--flag="other options" --verbose

Solution 5

You can use SHIFT for this. It removes %1 and shifts all other arguments one lower. This script outputs all the arguments after %2 (so it outputs %3, %4...) until one of them is empty (so it's the last one):

@echo off

SHIFT
SHIFT

:loop
if "%1" == "" goto end
echo %1
SHIFT
goto loop

:end

EDIT: Removed example using %* as this doesn't work - %* always outputs all of the parameters

Share:
37,815
noamtm
Author by

noamtm

Senior Software Engineer. Tech Lead at Kaltura.

Updated on July 09, 2022

Comments

  • noamtm
    noamtm almost 2 years

    Duplicate:

    Clarification: I knew of the looping approach - this worked even before Command Extensions; I was hoping for something fun and undocumented like %~*1 or whatever - just like those documented at http://www.microsoft.com/resources/documentation/windows/xp/all/proddocs/en-us/percent.mspx?mfr=true.


    In a Windows batch file (with the so called "Command Extensions" on), %1 is the first argument, %2 is the second, etc. %* is all arguments concatenated.

    My question: is there a way to get everything AFTER %2, for example?

    I couldn't find such a thing, and it would be helpful for something I'm working on.

  • OscarRyz
    OscarRyz about 15 years
    Just like in sh? Great! +1 . Do you happen to know what's the powershell option?
  • Dijar
    Dijar about 15 years
    Sorry, haven't used powershell yet.
  • Livven
    Livven over 10 years
    There's a small problem with this answer – RESTVAR will contain a leading space. Here's a slightly better version stackoverflow.com/a/761658/1488656
  • Chris Watts
    Chris Watts about 9 years
    For 'all-but-n', replace tokens=1 with tokens=n. The remaining arguments will still be in %%b
  • FremyCompany
    FremyCompany about 9 years
    In some cases, you may need to use !ALL_BUT_FIRST! instead of %ALL_BUT_FIRST% (for instance if you're inside some other loop); see stackoverflow.com/questions/12423238/…
  • Max Truxa
    Max Truxa about 9 years
    Don't forget to use setlocal enabledelayedexpansion if you are working with !var!.
  • EM0
    EM0 over 8 years
    Doesn't work when a quoted parameter contains spaces, eg. all_but_first.bat "first arg" "second arg"
  • Mr. Smythe
    Mr. Smythe almost 7 years
    I really want an ELI5 version of that CALL SET line.
  • Dmitry Sokolov
    Dmitry Sokolov almost 7 years
    Advanced usage : CALLing internal commands. It works like setlocal EnableDelayedExpansion + set _tail=!_all:*%2=!.
  • Raman Zhylich
    Raman Zhylich almost 7 years
    It will fail on this one: get_tail.cmd -s -s arg1
  • LINEMAN78
    LINEMAN78 over 6 years
    Doesn't work when an argument contains an '=' ie debug=1 becomes debug 1.
  • David Gausmann
    David Gausmann over 6 years
    This is the best solution for me, because the other solutions cropped my commas in the parameters.
  • cdlvcdlv
    cdlvcdlv about 6 years
    I think this is the only fail-safe answer and one of the simplest. It should be the accepted one.
  • HelloWorld
    HelloWorld over 5 years
    Good answer. But there is an error on statement. It worked when i change "%1" to "%~1".
  • binki
    binki over 5 years
    It looks like you’re doing a string replacement of the first argument against the entire set of arguments. That will fail, like @RamanZhylich said, if your first argument happens to be substring of any of your subsequent arguments. This is bad in the same way as @MaxTruxa’s answer but almost worse because it isn’t as obviously wrong.
  • binki
    binki over 5 years
    I naively assumed this approach would work, realized that %* doesn’t update when using SHIFT, and then came to this SO question searching for a solution. Looks like you did the opposite :-p
  • binki
    binki over 5 years
    Please explain how this only replaces 1 instance of the string because the replacement portion of the string replace starts with * which makes it magical: gist.github.com/binki/a96bbf9a282616671ecd7386a9f17510 ss64.com/nt/syntax-replace.html
  • bers
    bers almost 5 years
    For me, %_tail% has a leading space.
  • iki
    iki about 3 years
    Nice one, has leading space (just know about it, should not be an issue), and returns *= for no args, so you better check if they are not empty if not "%~1"=="" call set _tail=%%_tail:*%1=%%
  • iki
    iki about 3 years
    Works for me even with spaces, treats all = and , as arg separators
  • iki
    iki about 3 years
    Also treats all = and , as arg separators for me
  • iuzuz
    iuzuz over 2 years
    For what is the call keyword? Would simply "set.." without "call" not work?