Как получить параметры пакетного файла из N-й позиции?

В дополнение к Как передать параметры командной строки в пакетном файле, как получить остальные параметры, указав их точно? Я не хочу использовать SHIFT, потому что я не знаю, сколько параметров там может быть, и хотелось бы избежать их подсчета, если можно.

Например, данный пакетный файл:

@echo off
set par1=%1
set par2=%2
set par3=%3
set therest=%???
echo the script is %0
echo Parameter 1 is %par1%
echo Parameter 2 is %par2%
echo Parameter 3 is %par3%
echo and the rest are %therest%

Запуск mybatch opt1 opt2 opt3 opt4 opt5 ...opt20 даст:

the script is mybatch
Parameter 1 is opt1
Parameter 2 is opt2
Parameter 3 is opt3
and the rest are opt4 opt5 ...opt20

Я знаю, что %* дает все параметры, но я не делаю первые три (например).

Ответ 1

Здесь вы можете сделать это, не используя SHIFT:

@echo off

for /f "tokens=1-3*" %%a in ("%*") do (
    set par1=%%a
    set par2=%%b
    set par3=%%c
    set therest=%%d
)

echo the script is %0
echo Parameter 1 is %par1%
echo Parameter 2 is %par2%
echo Parameter 3 is %par3%
echo and the rest are %therest%

Ответ 2

Но здесь вы знаете, сколько будет. Вы знаете, что у вас будет три. Сдвиг три раза, а остальные параметры находятся в %*. То есть, когда вы используете shift, вы изменяете кажущееся значение %* для представления только тех параметров, которые вы еще не сдвинули.

Ответ 3

В следующем коде используется shift, но он избегает синтаксического анализа командной строки с помощью for и позволяет интерпретатору командной строки выполнять это задание (учитывая, что for не анализирует двойные кавычки должным образом, например, набор аргументов A B" "C интерпретируется как 3 аргумента A, B", "C на for, но как интерпретатор интерпретирует 2 аргумента A, B" "C, это предотвращает аргументы цитированного пути, такие как "C:\Program Files\" from правильное обращение):

@echo off

set "par1=%1" & shift /1
set "par2=%1" & shift /1
set "par3=%1" & shift /1

set therest=
set delim=

:REPEAT
if "%1"=="" goto :UNTIL
set "therest=%therest%%delim%%1"
set "delim= "
shift /1
goto :REPEAT
:UNTIL

echo the script is "%0"
echo Parameter 1 is "%par1%"
echo Parameter 2 is "%par2%"
echo Parameter 3 is "%par3%"
echo and the rest are "%therest%"
rem.the additional double-quotes in the above echoes^
    are intended to visualise potential whitespaces

Остальные аргументы в %therest% могут не выглядеть так, как они были первоначально в отношении разделителей (помните, что интерпретатор командной строки также рассматривает TAB, ,, ;, = как разделители, так и все комбинации), так как все разделители заменяются одним пробелом. Однако, передавая %therest% в какой-либо другой командный или командный файл, он будет корректно разбираться.

Единственное ограничение, с которым я столкнулся до сих пор, относится к аргументам, содержащим символ каретки ^. Другие ограничения (связанные с <, >, |, &, ") применяются к самому интерпретатору командной строки.

Ответ 4

@ECHO OFF
SET REST=
::# Guess you want 3rd and on.
CALL :SUBPUSH 3 %*
::# ':~1' here is merely to drop leading space.
ECHO REST=%REST:~1%
GOTO :EOF

:SUBPUSH
SET /A LAST=%1-1
SHIFT
::# Let throw the first two away.
FOR /L %%z in (1,1,%LAST%) do (
  SHIFT
)
:aloop
SET PAR=%~1
IF "x%PAR%" == "x" (
  GOTO :EOF
)
ECHO PAR=%PAR%
SET REST=%REST% "%PAR%"
SHIFT
GOTO aloop
GOTO :EOF

Мне нравится использовать подпрограммы вместо EnableDelayedExpansion. Выше - извлечение из моей партии обработки файла dir/file. Не говорите, что это не может обрабатывать аргументы с помощью =, но, по крайней мере, может выполнять цитируемый путь с пробелами и подстановочными знаками.