2009-04-17 3 views
34

Im folgenden Beispiel möchte ich eine untergeordnete Batchdatei aus einer übergeordneten Batchdatei aufrufen und alle verbleibenden Parameter an das untergeordnete Element übergeben.Gibt es eine Möglichkeit, die letzten n Parameter in einer Batchdatei anzugeben?

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 

Innen parent.cmd, ich brauche% 1 von der Liste der Parameter abzustreifen und nur die restlichen Parameter für das Kind Skript übergeben.

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

Ich habe mit SHIFT mit% * untersucht, aber das funktioniert nicht. Während SHIFT die Positionsparameter um 1 nach unten verschiebt, bezieht sich% * immer noch auf die ursprünglichen Parameter.

Wer hat irgendwelche Ideen? Soll ich einfach aufgeben und Linux installieren?

+0

Genaues Duplikat? http://stackoverflow.com/questions/382587/how-to-get-batch-file-parameters-from-nth-position-on –

+0

Diese Frage wurde mit Code beantwortet, der nicht funktionierte. Ich fügte Erklärungen zu meiner Frage hinzu, um zur Klärung beizutragen, und es sieht so aus, als hätte ich eine solide Antwort von Johannes bekommen. – Dave

+0

Oh, übrigens, wenn Chargen aus anderen Chargen von allen Maens Aufruf Anruf aufrufen. Andernfalls wird die aufrufende Stapeldatei nicht weiter ausgeführt, nachdem der aufgerufene Stapel beendet wurde. (Kann oder darf hier nicht relevant sein, nur einige Best Practices :-)) – Joey

Antwort

62

%* wird immer auf alle ursprünglichen Parameter, leider erweitert. Aber Sie können den folgenden Code-Snippet verwenden, um eine Variable zu bauen alle enthalten, aber den ersten Parameter:

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

ich denke, es kürzer gemacht werden kann, aber ... Ich schreibe nicht diese Art von Dingen sehr oft :)

Sollte funktionieren, obwohl.

+0

Wie Tbee sagte, funktioniert das nicht, wenn Sie '=' in Ihren verbleibenden Argumenten haben. Scheint als wäre der einzige wirkliche Weg, dies zu lösen, ein Programm zu schreiben, um die Argumente korrekt zu extrahieren - die cmd-Shell ist einfach zu schlampig. –

+3

Dieser Ansatz schlägt fehl, wenn Sie Zuordnungen in den Parametern haben, z. "a = b". Dann erhalten Sie zwei separate Parameter "a" und "b", die = verlieren. – Tbee

+2

In diesem Fall zitieren Sie das Argument. 'cmd' betrachtet einige weitere Zeichen als Argumenttrennzeichen, wie zum Beispiel'; 'oder', '. – Joey

14

Hier ist eine einzeilige Ansatz der „für“ Befehl ...

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

diesem Befehl wird der erste Parameter zuordnet „i“ und der Rest (bezeichnet mit ‚*‘) zugeordnet sind " j ", mit dem dann die Variable" params "gesetzt wird.

+0

Dies schlägt fehl, wenn das erste Argument ein Leerzeichen (zitiert) enthält, zB '" erstes Argument "zweite dritte' setzt Parameter auf 'Argument" zweite dritte " – EM0

5

Sie können eigentlich nur dies tun:

%* 

Wenn das das einzige, was auf dem Spiel steht, dann ist das der erste Parameter auf, die erweitert der Befehl ausgeführt, wobei alle anderen Parameter an sie übergeben . :)

1

Ein anderer Weg (fast die gleiche wie Alxander Vogel) ohne ECHO Ausführung in einer Subshell:

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

so, Linie

%CMD% <WHAT DO I PUT HERE> 

aussehen wird:

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

Das Problem besteht darin, dass cmd.exe die Parameter für die Verwendung von a korrekt analysiert, wenn die Parameter in Anführungszeichen gesetzte Leerzeichen enthalten s nummerierte Argumente (% 1), aber FOR ignoriert die Anführungszeichen. In diesem speziellen Fall wird es schaden, wenn der erste Parameter ein Leerzeichen oder mehr enthält, was durchaus möglich ist, wenn man bedenkt, dass% CMD% beispielsweise "C: \ Programme \ Internet Explorer \ iexplore.exe" sein kann.

Also, hier wird eine andere Antwort sein.

7

die Linie

%CMD% <WHAT DO I PUT HERE> 

soll geändert werden:

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

natürlich, können Sie auf eine beliebige Anzahl von Argumenten überspringen gesetzt.

0

wirklich Obwohl die ‚für‘ Lösung überlegen ist in vielen Fällen für die einfache etwas werde ich häufig nur die anderen Argumente weg speichern und verschieben, dann %* wie gewohnt verwenden (praktisch die gleiche Strategie funktioniert oft für $* oder [email protected] in {,ba,da,k,*}sh):

Beispiel:

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

Wie auch immer, ich sah, war die Frage lange beantwortet, aber dachte, ich würde dr Op in meinen zwei Cent, da es etwas war, das ich nicht sah, und weil es die Antwort war, die ich brauchte, als ich vor ein paar Jahren endlich darüber hinwegkam ... und "oh ... duh" ging. :)

+1

Verschiebung wirkt sich nicht% * Dies übergibt * alle * ursprünglichen Argumente an% run_me%, einschließlich% 1 und% 2. Wie die akzeptierte Antwort sagt, "% * wird immer auf alle ursprünglichen Parameter erweitert, leider." – Naaff

0

Ich stieß auf diese Frage, während ich ein ähnliches Problem hatte, aber ich löste es mit einem anderen Ansatz. Anstatt die Eingabezeile mit einer Schleife neu zu erstellen (wie in der Antwort von @Joey), entfernte ich einfach den ersten Parameter aus der Eingabezeichenfolge.

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

Dies setzt natürlich voraus, dass alle Parameter unterschiedlich sind.

Verwandte Themen