有没有办法在批处理文件中指出最后n个参数?

Dav*_*ave 40 parameters shell cmd

在以下示例中,我想从父批处理文件中调用子批处理文件,并将所有剩余参数传递给子代.

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
Run Code Online (Sandbox Code Playgroud)

在parent.cmd中,我需要从参数列表中删除%1,并仅将剩余参数传递给子脚本.

set CMD=%1
%CMD% <WHAT DO I PUT HERE>
Run Code Online (Sandbox Code Playgroud)

我已经调查过使用SHIFT和%*,但这不起作用.当SHIFT将位置参数向下移动1时,%*仍然指向原始参数.

有人有主意吗?我应该放弃并安装Linux吗?

Joe*_*oey 71

%*遗憾的是,它将永远扩展到所有原始参数.但是您可以使用以下代码片段来构建包含除第一个参数之外的所有参数的变量:

rem throw the first parameter away
shift
set params=%1
:loop
shift
if [%1]==[] goto afterloop
set params=%params% %1
goto loop
:afterloop
Run Code Online (Sandbox Code Playgroud)

我认为它可以做得更短,但是......我不经常写这些东西:)

不过应该工作.

  • 如果您在参数中有分配,则此方法将失败,例如"a = b".然后你会得到两个单独的参数"a"和"b",失去了=. (3认同)
  • 在这种情况下,引用参数.`cmd`也考虑了几个字符作为参数分隔符,例如`;`或`,`. (2认同)

小智 15

这是使用"for"命令的单行方法......

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

该命令将第一个参数分配给"i",其余的(用'*'表示)分配给"j",然后用于设置"params"变量.

  • 当第一个参数包含空格(引用)时,这会失败,例如``"first argument"second third``将params设置为`argument"second third" (3认同)

Log*_*mon 10

这条线

%CMD% <WHAT DO I PUT HERE>
Run Code Online (Sandbox Code Playgroud)

应改为:

(
  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%
Run Code Online (Sandbox Code Playgroud)

当然,您可以将skip var 设置为任意数量的参数.

Explaned:

(
@rem Starting block here, because it's read once and executed as one
@rem otherwise cmd.exe reads file line by line, which is waaay slower.

SETLOCAL ENABLEDELAYEDEXPANSION
SET skip=1

@rem if value contains unquoted non-paired parenthesis, SET varname=value 
@rem confuses cmd.exe. SET "a=value" works better even if value has quotes.
  FOR %%I IN (%*) DO (
    IF !skip! LEQ 0 (
      SET "params=!params! %%I"
      @rem newline after SET to lower amount of pitfalls when arguments 
      @rem have unpaired quotes
    ) ELSE (
      SET /A skip-=1
    )
)
(
@rem get variables out of SETLOCAL block
@rem as whole block in parenthesis is read and expanded before executing,
@rem SET after ENDLOCAL in same block will set var to what it was before
@rem ENDLOCAL. All other envvars will be reset to state before SETLOCAL.
ENDLOCAL
SET "params=%params%"
)
@rem doing this outside of parenthesis block to avoid
@rem cmd.exe confusion if params contain unquoted closing round bracket
%CMD% %params%
Run Code Online (Sandbox Code Playgroud)


Ale*_*ird 7

你实际上可以这样做:

%*
Run Code Online (Sandbox Code Playgroud)

如果这是该行上的唯一内容,则扩展为将第一个参数作为执行的命令,并将所有其他参数传递给它.:)