2009-04-17 5 views
34

En el siguiente ejemplo, deseo llamar a un archivo por lotes hijo desde un archivo por lotes principal y pasar todos los parámetros restantes al secundario.¿Hay alguna forma de indicar los últimos n parámetros en un archivo por lotes?

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 

Dentro parent.cmd, tengo que quitar% 1 de la lista de parámetros y sólo pasar el resto de parámetros al script niño.

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

He investigado el uso de MAYÚS con% *, pero eso no funciona. Mientras SHIFT moverá los parámetros posicionales hacia abajo en 1,% * todavía se refiere a los parámetros originales.

¿Alguien tiene alguna idea? ¿Debería renunciar e instalar Linux?

+0

¿Duplicado exacto? http://stackoverflow.com/questions/382587/how-to-get-batch-file-files-from-nth-position-on –

+0

Esa pregunta fue respondida con un código que no funcionó. Agregué declaraciones a mi pregunta para ayudar a aclarar, y parece que obtuve una respuesta sólida de Johannes. – Dave

+0

Ah, dicho sea de paso, al llamar lotes de otros lotes por todas las mans, use llamar. De lo contrario, el archivo por lotes de llamada no se ejecutará más después de que salga el lote llamado. (Puede o no ser relevante aquí, solo algunas mejores prácticas :-)) – Joey

Respuesta

62

%* siempre se ampliará a todos los parámetros originales, por desgracia. Sin embargo, se puede utilizar el siguiente fragmento de código para construir una variable que contiene todos menos el primer parámetro:

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

Creo que se puede hacer más corta, aunque ... No escribo este tipo de cosas muy a menudo :)

Debería funcionar, sin embargo.

+0

Como dijo Tbee, esto no funciona si tienes '=' dentro de tus argumentos restantes. Parece que la única manera real de resolver esto es escribir un programa para extraer correctamente tus argumentos: el shell cmd es demasiado descuidado. –

+3

Este enfoque falla si tiene asignaciones en los parámetros, p. "a = b". Entonces obtendrá dos parámetros separados "a" y "b", perdiendo el =. – Tbee

+2

En ese caso, cite el argumento. 'cmd' también considera algunos caracteres más para ser separadores de argumento, como'; 'o', '. – Joey

14

Aquí es un enfoque de una sola línea utilizando el "para" comando ...

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

Este comando asigna el primero parámetro en "i" y el resto (denotado por '*') son asignados a " j ", que luego se usa para establecer la variable" params ".

+0

Esto falla cuando el primer argumento contiene un espacio (citado), por ejemplo '" primer argumento "segundo tercero' establece params a' argumento "segundo tercero' – EM0

5

Usted puede simplemente hacer esto:

%* 

Si esa es la única cosa en la línea, a continuación, que se expande para tener el primer parámetro ser el comando ejecutado, con todos los demás parámetros que recibe . :)

1

Otra forma (casi lo mismo que Alxander Bird) sin ejecutar ECHO en un subnivel:

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

así, la línea

%CMD% <WHAT DO I PUT HERE> 

será parecida:

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

el problema es que si los parámetros incluyen picaduras entre comillas con espacios dentro, cmd.exe las analizará de forma apropiada para usar una s argumentos numerados (% 1), pero FOR ignorará las comillas. En este caso específico, dañará si el primer parámetro incluye un espacio o más, lo cual es bastante posible, considerando que% CMD% puede ser, por ejemplo, "C: \ Archivos de programa \ Internet Explorer \ iexplore.exe".

Entonces, aquí hay otra respuesta.

7

la línea

%CMD% <WHAT DO I PUT HERE> 

serán cambiados a:

(
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% 

por supuesto, es posible establecer Saltar a cualquier número de argumentos.

0

Aunque en realidad el 'para' la solución es superior en muchas circunstancias, por algo sencillo voy a menudo, simplemente, guardar y cambiar los otros argumentos de distancia, a continuación, utilizar %* como de costumbre (prácticamente la misma estrategia a menudo trabaja para $* o [email protected] en {,ba,da,k,*}sh):

ejemplo:

:: 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% 

de todos modos, vi la pregunta fue respondida largo, pero pensé que podría dr op en mis dos centavos ya que era algo que no veía, y porque era la respuesta que necesitaba cuando finalmente me crucé con ella hace unos años ... y dije "oh ... duh". :)

+1

shift no afecta% * entonces esto pasa * todos * argumentos originales a% run_me%, incluyendo% 1 y% 2. Como la respuesta aceptada dice "% * siempre se expandirá a todos los parámetros originales, por desgracia". – Naaff

0

Me encontré con esta pregunta cuando me enfrentaba a un problema similar, pero lo resolví con un enfoque diferente. En lugar de volver a crear la línea de entrada usando un bucle (como en la respuesta de @Joey) simplemente eliminé el primer parámetro de la cadena de entrada.

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

Por supuesto, esto supone que todos los parámetros son diferentes.

Cuestiones relacionadas