可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
In the following example, I want to call a child batch file from a parent batch file and pass all of the remaining parameters to the child.
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
Inside parent.cmd, I need to strip %1 off the list of parameters and only pass the remaining parameters to the child script.
set CMD=%1
%CMD% <WHAT DO I PUT HERE>
I've investigated using SHIFT with %*, but that doesn't work. While SHIFT will move the positional parameters down by 1, %* still refers to the original parameters.
Anyone have any ideas? Should I just give up and install Linux?
回答1:
%*
will always expand to all original parameters, sadly. But you can use the following snippet of code to build a variable containing all but the first parameter:
rem throw the first parameter away
shift
set params=%1
:loop
shift
if [%1]==[] goto afterloop
set params=%params% %1
goto loop
:afterloop
I think it can be done shorter, though ... I don't write these sort of things very often :)
Should work, though.
回答2:
Here's a one-line approach using the "for" command...
for /f "usebackq tokens=1*" %%i in (`echo %*`) DO @ set params=%%j
This command assigns the 1st parameter to "i" and the rest (denoted by '*') are assigned to "j", which is then used to set the "params" variable.
回答3:
the line
%CMD% <WHAT DO I PUT HERE>
shall be changed to:
(
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%
of course, you may set Skip to any number of arguments.
回答4:
You can actually just do this:
%*
If that is the only thing on the line, then that expands to having the first parameter be the command executed, with all other parameters passed to it. :)
回答5:
Another way (almost the same as Alxander Bird's) without executing ECHO in a subshell:
FOR /F "usebackq tokens=1*" %%I IN ('%*') DO SET params=%%J
so, line
%CMD% <WHAT DO I PUT HERE>
will look like:
FOR /F "usebackq tokens=1*" %%I IN ('%*') DO %CMD% %%J
the problem is that if parameters include quoted stings with spaces inside, cmd.exe will parse them appropriately for using as numbered arguments (%1), but FOR will ignore the quotes. This specific case, it will harm if first parameter includes a space or more, which is quite possible, considering %CMD% can be, for example, "C:\Program Files\Internet Explorer\iexplore.exe".
So, here will be another answer.
回答6:
I have improved Moshe Goren's answer because it didn't seem to work for me:
set _input=%*
call set params=%%_input:%1 =%%
@echo %params%
回答7:
Although really the 'for' solution is superior in a lot of circumstances, for something simple I will frequently just save and shift the other arguments away, then use %*
as usual (practically the same strategy often works for $*
or $@
in {,ba,da,k,*}sh
):
example:
:: 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%
Anyhow, I saw the question was long answered, but figured I'd drop in my two cents as it was something I didn't see, and because it was the answer I needed when I finally happened across it a few years back... and went "oh... duh." :)
回答8:
I came across this question while I was facing a similar problem, but I solved it using a different approach.
Instead of re-creating the input line using a loop (as in the answer by @Joey) I simply removed the first parameter from the input string.
set _input=%*
set params=!_input:%1 =!
call OTHER_BATCH_FILE.cmd %params%
Of course, this assumes that all the parameters are different.