Есть ли способ указать последние n параметров в пакетном файле?

В следующем примере я хочу вызвать дочерний пакетный файл из родительского пакетного файла и передать все остальные параметры дочернему.

C:\> parent.cmd child1 foo bar
C:\> parent.cmd child2 baz zoop
C:\> parent.cmd child3 a b c d e f g h i j k l m n o p q r s t u v w x y z

Внутри parent.cmd мне нужно удалить% 1 из списка параметров и передать оставшиеся параметры дочернему элементу script.

set CMD=%1
%CMD% <WHAT DO I PUT HERE>

Я исследовал использование SHIFT с% *, но это не работает. Хотя SHIFT будет перемещать позиционные параметры вниз на 1,% * по-прежнему относится к исходным параметрам.

У кого-нибудь есть идеи? Должен ли я просто отказаться и установить Linux?

Ответ 1

%*, к сожалению, всегда будет распространяться на все исходные параметры. Но вы можете использовать следующий фрагмент кода для создания переменной, содержащей все, кроме первого параметра:

rem throw the first parameter away
shift
set params=%1
:loop
shift
if [%1]==[] goto afterloop
set params=%params% %1
goto loop
:afterloop

Я думаю, что это можно сделать короче, хотя... Я не пишу такого рода вещи очень часто:)

Должен работать, однако.

Ответ 2

Здесь однострочный подход с использованием команды "для"...

for /f "usebackq tokens=1*" %%i in (`echo %*`) DO @ set params=%%j

Эта команда назначает 1-й параметр "i", а остальная часть (обозначается "*" ) назначается "j", которая затем используется для установки переменной "params".

Ответ 3

строка

%CMD% <WHAT DO I PUT HERE>

должно быть изменено на:

(
SETLOCAL ENABLEDELAYEDEXPANSION
SET Skip=1

FOR %%I IN (%*) DO IF !Skip! LEQ 0 ( 
        SET params=!params! %%I
    ) ELSE SET /A Skip-=1
)
(
ENDLOCAL
SET params=%params%
)
%CMD% %params%

конечно, вы можете установить Skip на любое количество аргументов.

Ответ 4

Вы можете просто сделать это:

%*

Если это единственное в строке, то это расширяется до того, что будет выполняться первый параметр, а все остальные параметры переданы ему.:)

Ответ 5

Другой способ (почти такой же, как Alxander Bird) без выполнения ECHO в подоболочке:

FOR /F "usebackq tokens=1*" %%I IN ('%*') DO SET params=%%J

так, строка

%CMD% <WHAT DO I PUT HERE>

будет выглядеть так:

FOR /F "usebackq tokens=1*" %%I IN ('%*') DO %CMD% %%J

проблема заключается в том, что если параметры включают цитируемые stings с пробелами внутри, cmd.exe будет правильно их анализировать для использования в качестве пронумерованных аргументов (% 1), но FOR будет игнорировать кавычки. В этом конкретном случае это вредит, если первый параметр содержит пробел или больше, что вполне возможно, учитывая, что% CMD% может быть, например, "C:\Program Files\Internet Explorer\iexplore.exe".

Итак, вот еще один ответ.

Ответ 6

Хотя на самом деле решение "для" превосходит в самых разных обстоятельствах, для чего-то простого я часто просто сохраняю и переношу другие аргументы, а затем использую %* как обычно (практически такая же стратегия часто работает для $* или [email protected] в {,ba,da,k,*}sh):

Пример:

:: run_and_time_me.cmd - run a command with the arguments passed, while also piping
::                       the output through a second passed-in executable

@echo off

set run_me=%1
set pipe_to_me=%2
shift
shift

:: or
:: set run_me=%1
:: shift
:: set pipe_to_me=%1
:: shift

%run_me% %* | %pipe_to_me%

Во всяком случае, я видел, что вопрос был долгим, но подумал, что я загляжу в свои два цента, потому что это было то, чего я не видел, и потому что это был тот ответ, который мне нужен, когда я, наконец, через несколько лет назад... и пошел "о... дух".:)

Ответ 7

Я столкнулся с этим вопросом, пока сталкивался с аналогичной проблемой, но решил это с помощью другого подхода. Вместо повторного создания строки ввода с использованием цикла (как в ответе @Joey) я просто удалил первый параметр из входной строки.

set _input=%*
set params=!_input:%1 =!
call OTHER_BATCH_FILE.cmd %params%

Конечно, это предполагает, что все параметры разные.