Liste der übergebenen Argumente im Windows-Batch-Skript (.bat) abrufen

405

Ich möchte ein Windows-Batch-Gegenstück zu Bash finden, $@das eine Liste aller an ein Skript übergebenen Argumente enthält.

Oder muss ich mich darum kümmern shift?

wheleph
quelle

Antworten:

622

dancavallaro hat das Recht %*für alle Befehlszeilenparameter (mit Ausnahme des Skriptnamens selbst). Sie könnten diese auch nützlich finden:

%0- der Befehl verwendet , um die Batch - Datei aufrufen (könnte foo, ..\foo, c:\bats\foo.batetc.)
%1ist der erste Kommandozeilenparameter,
%2ist der zweite Befehlszeilenparameter,
und so weiter , bis %9(und SHIFTkann für diejenigen , die nach dem 9. verwendet werden).

%~nx0- Der tatsächliche Name der Batchdatei, unabhängig von der aufrufenden Methode (some-batch.bat)
%~dp0- Laufwerk und Pfad zum Skript (d: \ scripts)
%~dpnx0- ist der vollständig qualifizierte Pfadname des Skripts (d: \ scripts \ some) -batch.bat)

Weitere Infobeispiele unter https://www.ss64.com/nt/syntax-args.html und https://www.robvanderwoude.com/parameters.html

matt wilkie
quelle
11
Beachten Sie, dass SHIFT% * nicht beeinflusst, sodass es unmöglich ist, SHIFT [/ n] für etwas Intuitives wie den Zugriff auf die gesamte Befehlszeile ab dem n-ten Parameter zu verwenden.
Van Jone
4
Ich habe außerdem festgestellt, dass %~dpn0das Laufwerk und der Pfad zum Skript sowie der Name der Batchdatei zurückgegeben werden, nicht jedoch die Erweiterung. Ich fand dies besonders nützlich beim Erstellen von Batch-Skripten, die eine .ps1Datei mit demselben Namen aufrufen . Im Wesentlichen dbezieht sich das auf das Laufwerk, pauf den Pfad, nauf den Namen der Datei und xauf die Erweiterung. Mit diesen Informationen können Sie ziemlich viel tun.
Dan Atkinson
Angenommen, ich möchte ECHO verwenden, um den Pfad der Datei auszudrucken, aber ihre Erweiterung zu ersetzen. Wie würde das gehen?
Matheus Rocha
2
@ MatheusRocha@echo %~n0.my_ext
Matt Wilkie
@mattwilkie Danke, ich habe es mit ECHO herausgefunden, um zu sehen, was als Ergebnis gedruckt wird.
Matheus Rocha
149

%* scheint alle an das Skript übergebenen Argumente zu enthalten.

Dancavallaro
quelle
Irgendeine Idee, warum es einige Zeichen nicht behandelt wie &? Wenn ich versuche, mehrere Pfade mehrerer ausgewählter Dateien abzurufen (über das Menü Senden an und "% *", die die Argumente an eine .py-Datei übergeben), wird die Auflistung bei & caracters gestoppt. Wenn zum Beispiel die zweite Datei ein &in ihrem Namen enthält, wird der Teil des Namens nach dem &übersprungen, und auch die verbleibenden Dateien.)
JinSnow
1
@ JinSnow Das &ist ein Sonderzeichen, das bedeutet stop this command and start another one. Ein Dateiname mit einem & MUSS angegeben werden.
Jesse Chisholm
65

%1... %nund %*enthält die Argumente, aber es kann schwierig sein, darauf zuzugreifen, da der Inhalt interpretiert wird.
Daher ist es unmöglich, so etwas mit normalen Aussagen zu handhaben

myBatch.bat "&"^&

Jede Zeile schlägt fehl, da cmd.exe versucht, eines der kaufmännischen Und-Zeichen auszuführen (der Inhalt von% 1 ist "&"&).

set var=%1
set "var=%1"
set var=%~1
set "var=%~1"

Es gibt jedoch eine Problemumgehung mit einer temporären Datei

@echo off
SETLOCAL DisableDelayedExpansion

SETLOCAL
for %%a in (1) do (
    set "prompt=$_"
    echo on
    for %%b in (1) do rem * #%1#
    @echo off
) > param.txt
ENDLOCAL

for /F "delims=" %%L in (param.txt) do (
  set "param1=%%L"
)
SETLOCAL EnableDelayedExpansion
set "param1=!param1:*#=!"
set "param1=!param1:~0,-2!"
echo %%1 is '!param1!'

Der Trick besteht darin echo on, die %1After- remAnweisung zu aktivieren und zu erweitern (funktioniert auch mit% 2 ..% *). Um
die Ausgabe von umleiten zu können echo on, benötigen Sie die beiden FOR-LOOPS.

Die zusätzlichen Zeichen * #werden verwendet, um gegen Inhalte wie /?(würde die Hilfe für REM zeigen) sicher zu sein .
Oder ein Caret ^ am Zeilenende könnte als mehrzeiliges Zeichen fungieren.

Das FOR / F sollte mit verzögerter Erweiterung arbeiten, sonst Inhalt mit "!" würde zerstört werden.
Nachdem Sie die zusätzlichen Zeichen entfernt haben, haben param1Sie sie erhalten.

param1Aktivieren Sie die verzögerte Erweiterung, um eine sichere Verwendung zu gewährleisten.

Bearbeiten: Eine Bemerkung zu% 0

%0enthält den Befehl zum Aufrufen des Stapels, wobei auch die Groß- / Kleinschreibung wie in FoO.BaT
Aber nach einem Aufruf einer Funktion beibehalten wird, %0und %~0enthält auch den Funktionsnamen (oder besser die Zeichenfolge, die zum Aufrufen der Funktion verwendet wurde).
Aber mit können %~f0Sie immer noch den Dateinamen abrufen.

@echo off
echo main %0, %~0, %~f0
call :myLabel+xyz
exit /b

:MYlabel
echo func %0, %~0, %~f0
exit /b

Ausgabe

main test.bat, test.bat, C:\temp\test.bat
func :myLabel+xyz, :myLabel+xyz, C:\temp\test.bat
jeb
quelle
6
+++ 1 OMG - Der %~f0Trick ist völlig unerwartet, sehr cool und möglicherweise sehr nützlich :-) Es überrascht nicht, dass die anderen Modifikatoren auf die gleiche Weise funktionieren und immer mit der übergeordneten Batchdatei arbeiten, selbst wenn sie sich in einer aufgerufenen Unterroutine befinden. Dies scheint eine eigene Frage und Antwort wert zu sein - "Wie kann man in einem aufgerufenen Unterprogramm auf den Namen des laufenden Stapels zugreifen?"
Dbenham
Wenn ich mich richtig erinnere, können Sie call mit Argumenten verwenden, und diese werden in% 1,% 2, ...% n gespeichert, genau wie beim Ausführen eines Skripts.
Nulano
49

Ich habe das beim nächsten Mal gefunden, wenn Sie diese Informationen nachschlagen müssen. Anstatt einen Browser zu öffnen und zu googeln, können Sie einfach call /?Ihr cmd eingeben und Sie erhalten es:

...

%* in a batch script refers to all the arguments (e.g. %1 %2 %3
    %4 %5 ...)

Substitution of batch parameters (%n) has been enhanced.  You can
now use the following optional syntax:

    %~1         - expands %1 removing any surrounding quotes (")
    %~f1        - expands %1 to a fully qualified path name
    %~d1        - expands %1 to a drive letter only
    %~p1        - expands %1 to a path only
    %~n1        - expands %1 to a file name only
    %~x1        - expands %1 to a file extension only
    %~s1        - expanded path contains short names only
    %~a1        - expands %1 to file attributes
    %~t1        - expands %1 to date/time of file
    %~z1        - expands %1 to size of file
    %~$PATH:1   - searches the directories listed in the PATH
                   environment variable and expands %1 to the fully
                   qualified name of the first one found.  If the
                   environment variable name is not defined or the
                   file is not found by the search, then this
                   modifier expands to the empty string

The modifiers can be combined to get compound results:

    %~dp1       - expands %1 to a drive letter and path only
    %~nx1       - expands %1 to a file name and extension only
    %~dp$PATH:1 - searches the directories listed in the PATH
                   environment variable for %1 and expands to the
                   drive letter and path of the first one found.
    %~ftza1     - expands %1 to a DIR like output line

In the above examples %1 and PATH can be replaced by other
valid values.  The %~ syntax is terminated by a valid argument
number.  The %~ modifiers may not be used with %*
KFL
quelle
20

Der Weg, um alle Argumente in ein Skript abzurufen, ist hier:

@ECHO off
ECHO The %~nx0 script args are...
for %%I IN (%*) DO ECHO %%I
pause
Djangofan
quelle
2
Nicht wirklich, lassen Sie %%Isich interpretieren und brechen Sie möglicherweise Ihr Skript.
Boris Brodski
5

Hier ist eine ziemlich einfache Möglichkeit, die Argumente abzurufen und als env-Variablen festzulegen. In diesem Beispiel werde ich sie nur als Schlüssel und Werte bezeichnen.

Speichern Sie das folgende Codebeispiel als "args.bat". Rufen Sie dann die Batchdatei auf, die Sie über eine Befehlszeile gespeichert haben. Beispiel: arg.bat --x 90 --y 120

Ich habe einige Echo-Befehle bereitgestellt, um Sie durch den Prozess zu führen. Das Endergebnis ist jedoch, dass --x einen Wert von 90 und --y einen Wert von 120 hat (wenn Sie das Beispiel wie oben angegeben ausführen ;-)).

Sie können dann die bedingte Anweisung 'if defined' verwenden, um zu bestimmen, ob Ihr Codeblock ausgeführt werden soll oder nicht. Sagen wir also run: "arg.bat --x hello-world" Ich könnte dann die Anweisung "IF DEFINED --x echo% - x%" verwenden und die Ergebnisse wären "hallo-world". Es sollte sinnvoller sein, wenn Sie den Stapel ausführen.

@setlocal enableextensions enabledelayedexpansion
@ECHO off
ECHO.
ECHO :::::::::::::::::::::::::: arg.bat example :::::::::::::::::::::::::::::::
ECHO :: By:      User2631477, 2013-07-29                                   ::
ECHO :: Version: 1.0                                                         ::
ECHO :: Purpose: Checks the args passed to the batch.                        ::
ECHO ::                                                                      ::
ECHO :: Start by gathering all the args with the %%* in a for loop.          ::
ECHO ::                                                                      ::
ECHO :: Now we use a 'for' loop to search for our keys which are identified  ::
ECHO :: by the text '--'. The function then sets the --arg ^= to the next    ::
ECHO :: arg. "CALL:Function_GetValue" ^<search for --^> ^<each arg^>         ::
ECHO ::                                                                      ::
ECHO ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

ECHO.

ECHO ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
ECHO :: From the command line you could pass... arg.bat --x 90 --y 220       ::
ECHO ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
ECHO.
ECHO.Checking Args:"%*"

FOR %%a IN (%*) do (
    CALL:Function_GetValue "--","%%a" 
)

ECHO.
ECHO ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
ECHO :: Now lets check which args were set to variables...                   ::
ECHO ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
ECHO.
ECHO ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
ECHO :: For this we are using the CALL:Function_Show_Defined "--x,--y,--z"   ::
ECHO ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
ECHO.
CALL:Function_Show_Defined "--x,--y,--z"
endlocal
goto done

:Function_GetValue

REM First we use find string to locate and search for the text.
echo.%~2 | findstr /C:"%~1" 1>nul

REM Next we check the errorlevel return to see if it contains a key or a value
REM and set the appropriate action.

if not errorlevel 1 (
  SET KEY=%~2
) ELSE (
  SET VALUE=%~2
)
IF DEFINED VALUE (
    SET %KEY%=%~2
    ECHO.
    ECHO ::::::::::::::::::::::::: %~0 ::::::::::::::::::::::::::::::
    ECHO :: The KEY:'%KEY%' is now set to the VALUE:'%VALUE%'                     ::
    ECHO :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    ECHO.
    ECHO %KEY%=%~2
    ECHO.
    REM It's important to clear the definitions for the key and value in order to
    REM search for the next key value set.
    SET KEY=
    SET VALUE=
)
GOTO:EOF

:Function_Show_Defined 
ECHO.
ECHO ::::::::::::::::::: %~0 ::::::::::::::::::::::::::::::::
ECHO :: Checks which args were defined i.e. %~2
ECHO :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
ECHO.
SET ARGS=%~1
for %%s in (%ARGS%) DO (
    ECHO.
    ECHO :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    ECHO :: For the ARG: '%%s'                         
    IF DEFINED %%s (
        ECHO :: Defined as: '%%s=!%%s!'                                             
    ) else (
        ECHO :: Not Defined '%%s' and thus has no value.
    )
    ECHO :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    ECHO.
)
goto:EOF

:done

quelle
Das ist sehr nützlich!
Robe007
3

Geben Sie hier die Bildbeschreibung ein

Für die Verwendung von Schleifen zum Abrufen aller Argumente und im reinen Stapel:

Obs: Für die Verwendung ohne:?*&<>


@echo off && setlocal EnableDelayedExpansion

for %%Z in (%*)do set "_arg_=%%Z" && set/a "_cnt+=1+0" && call set "_arg_[!_cnt!]=!_arg_!")

:: write/test these arguments/parameters ::
for /l %%l in (1 1 !_cnt!)do echo/ The argument n:%%l is: !_arg_[%%l]!

goto :eof 

Ihr Code ist bereit, etwas mit der Argumentnummer zu tun, wo es benötigt wird, wie ...

@echo off && setlocal EnableDelayedExpansion

for %%Z in (%*)do set "_arg_=%%Z" && set/a "_cnt+=1+0" && call set "_arg_[!_cnt!]=!_arg_!"

echo= !_arg_[1]! !_arg_[2]! !_arg_[2]!> log.txt
Ich war es nicht
quelle
2

Der folgende Code simuliert ein Array (' params') - nimmt die vom Skript empfangenen Parameter und speichert sie in den Variablen params_1.. params_n, wobei n= params_0= die Anzahl der Elemente des Arrays:

@echo off

rem Storing the program parameters into the array 'params':
rem Delayed expansion is left disabled in order not to interpret "!" in program parameters' values;
rem however, if a parameter is not quoted, special characters in it (like "^", "&", "|") get interpreted at program launch
set /a count=0
:repeat
    set /a count+=1
    set "params_%count%=%~1"
    shift
    if defined params_%count% (
        goto :repeat
    ) else (
        set /a count-=1
    )    
set /a params_0=count

rem Printing the program parameters stored in the array 'params':
rem After the variables params_1 .. params_n are set with the program parameters' values, delayed expansion can
rem be enabled and "!" are not interpreted in the variables params_1 .. params_n values
setlocal enabledelayedexpansion
    for /l %%i in (1,1,!params_0!) do (
        echo params_%%i: "!params_%%i!"
    )
endlocal

pause
goto :eof

quelle
1

Wenn Sie Parameter in Anführungszeichen haben, die Leerzeichen enthalten, %*funktioniert dies nicht richtig. Die beste Lösung, die ich gefunden habe, ist eine Schleife, die alle Argumente verbindet: https://serverfault.com/a/22541

set args=%1
shift
:start
if [%1] == [] goto done
set args=%args% %1
shift
goto start

:done
(use %args% here)
Speedstone
quelle
1

Sie können ForCommad verwenden, um eine Liste von Arg zu erhalten.

Hilfe: For /? Hilfe:Setlocal /?

Hier ist mein Weg =

@echo off
::For Run Use This = cmd /c ""Args.cmd" Hello USER Scientist etc"
setlocal EnableDelayedExpansion
set /a Count=0
for %%I IN (%*) DO (
 Echo Arg_!Count! = %%I
 set /a Count+=1 
)
Echo Count Of Args = !Count!
Endlocal

Benötigen Sie keinen Shift-Befehl.

Wissenschaftler_7
quelle
0
@echo aus
:Start

:: Geben Sie hier Ihren Code ein
Echo. %% 1 ist jetzt:% ~ 1
:: Geben Sie hier Ihren Code ein

wenn "% ~ 2" NEQ "" (
    Verschiebung
    gehe zu: fang an
)
user298107
quelle
0

Viele der oben genannten Informationen führten mich zu weiteren Nachforschungen und letztendlich zu meiner Antwort. Deshalb wollte ich dazu beitragen, was ich in der Hoffnung getan habe, dass es jemand anderem hilft:

  • Ich wollte auch eine unterschiedliche Anzahl von Variablen an eine Batch-Datei übergeben, damit sie innerhalb der Datei verarbeitet werden können.

  • Ich war damit einverstanden, sie mit Anführungszeichen an die Batch-Datei zu übergeben

  • Ich möchte, dass sie ähnlich wie unten verarbeitet werden - aber mit einer Schleife, anstatt manuell zu schreiben:

Also wollte ich folgendes ausführen:

prog_ZipDeleteFiles.bat "_appPath=C:\Services\Logs\PCAP" "_appFile=PCAP*.?"

Und über die Magie von for-Schleifen tun Sie dies in der Batch-Datei:

set "_appPath=C:\Services\Logs\PCAP"
set "_appFile=PCAP*.?"

Das Problem, das ich hatte, war, dass alle meine Versuche, eine for-Schleife zu verwenden, nicht funktionierten. Das folgende Beispiel:

for /f "tokens* delims= " in %%A (%*) DO (
   set %%A
)

würde einfach tun:

set "_appPath=C:\Services\Logs\PCAP"

und nicht:

set "_appPath=C:\Services\Logs\PCAP"
set "_appFile=PCAP*.?"

auch nach dem einstellen

SETLOCAL EnableDelayedExpansion

Grund war, dass die for-Schleife die gesamte Zeile gelesen und meinen zweiten Parameter während der ersten Iteration der Schleife %% B zugewiesen hat. Da% * alle Argumente darstellt, muss nur eine einzige Zeile verarbeitet werden - daher geschieht nur ein Durchgang der for-Schleife. Es stellt sich heraus, dass dies beabsichtigt ist, und meine Logik war falsch.

Also habe ich aufgehört, eine for-Schleife zu verwenden, und vereinfacht, was ich versucht habe, indem ich if, shift und eine goto-Anweisung verwendet habe. Ich bin damit einverstanden, dass es ein bisschen hackt, aber es passt besser zu meinen Bedürfnissen. Ich kann alle Argumente durchlaufen und dann eine if-Anweisung verwenden, um die Schleife zu verlassen, sobald ich sie alle verarbeitet habe.

Die gewinnende Aussage für das, was ich erreichen wollte:

echo on
:processArguments
:: Process all arguments in the order received
if defined %1 then (
    set %1
    shift
    goto:processArguments
) ELSE (
    echo off 
)

UPDATE - Ich musste stattdessen das Folgende ändern. Ich habe alle Umgebungsvariablen verfügbar gemacht, als ich versucht habe, auf% 1 zu verweisen und Shift auf diese Weise zu verwenden:

echo on
shift
:processArguments
:: Process all arguments in the order received
if defined %0 then (
    set %0
    shift
    goto:processArguments
) ELSE (
    echo off 
)
John Ahearn
quelle
Ich liege falsch, habe noch einige Überprüfungen durchgeführt und nach der 3. Iteration macht mein Shift-Befehl alle Umgebungsvariablen verfügbar, wodurch die oben genannten Fehler behoben werden. Ich prüfe immer noch, ob es einen Ausweg gibt.
John Ahearn
Musste eine Änderung vornehmen, anstatt% 1 zu verwenden, musste ich anfänglich einmal wechseln und% 0 verwenden, oder ich stieß auf ein seltsames Problem, bei dem% 1 schließlich alle aktuellen Umgebungsvariablen enthielt.
John Ahearn
0

Manchmal muss ich mehrere Befehlszeilenparameter extrahieren, aber nicht alle und nicht aus dem ersten. Nehmen wir den folgenden Aufruf an:

Test.bat uno dos tres cuatro cinco seis siete

Natürlich wird die Erweiterung ".bat" nicht benötigt, zumindest haben Sie test.exe im selben Ordner. Was wir wollen, ist die Ausgabe "tres cuatro cinco" (egal ob eine oder drei Zeilen). Das Ziel ist, dass nur ich drei Parameter benötige und mit dem dritten beginne. Um ein einfaches Beispiel zu haben, ist die Aktion für jedes nur "Echo", aber Sie können in einer anderen komplexeren Aktion über die ausgewählten Parameter nachdenken.

Ich habe einige Beispiele (Optionen) erstellt, damit Sie sehen können, welches für Sie besser ist. Leider gibt es keinen schönen (oder ich weiß nicht) Weg, der auf einer for-Schleife über den Bereich wie "für %% i in (% 3, 1,% 5)" basiert.

@echo off 
setlocal EnableDelayedExpansion

echo Option 1: one by one (same line)
echo %3, %4, %5
echo.

echo Option 2: Loop For one by one
for %%a in (%3, %4, %5) do echo %%a
echo.

echo Option 3: Loop For with check of limits
set i=0
for %%a in (%*) do (
    set /A i=i+1
    If !i! GTR 2 if !i! LSS 6 echo %%a
)
echo.

echo Option 4: Loop For with auxiliary list
for /l %%i in (3,1,5) do  (
    set a=%%i
    set b=echo %%
    set b=!b!!a!
    call !b!
)
echo.

echo Option 5: Assigning to an array of elements previously
set e[0]=%0
set i=0 
for %%a in (%*) do (
    set /A i=i+1
    set e[!i!]=%%a
)
for  /l %%i in (3,1,5) do (
    echo !e[%%i]!
)
echo.

echo Option 6: using shift and goto loop. It doesn't work with for loop
set i=2
:loop6
    set /A i=i+1
    echo %3
    shift
    If %i% LSS 5 goto :loop6

Wahrscheinlich können Sie mehr Optionen finden oder mehrere kombinieren. Genieße sie.

Fortu
quelle
-1

Windows-Version (benötigt jedoch Socat)

C:\Program Files (x86)\Git\bin>type gitproxy.cmd
socat STDIO PROXY:proxy.mycompany.de:%1:%2,proxyport=3128

Einrichten:

C:\Users\exhau\AppData\Roaming\npm>git config --global core.gitproxy gitproxy.cmd
Jabo
quelle