Antworten:
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.bat
etc.)
%1
ist der erste Kommandozeilenparameter,
%2
ist der zweite Befehlszeilenparameter,
und so weiter , bis %9
(und SHIFT
kann 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
%~dpn0
das 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 .ps1
Datei mit demselben Namen aufrufen . Im Wesentlichen d
bezieht sich das auf das Laufwerk, p
auf den Pfad, n
auf den Namen der Datei und x
auf die Erweiterung. Mit diesen Informationen können Sie ziemlich viel tun.
@echo %~n0.my_ext
%*
scheint alle an das Skript übergebenen Argumente zu enthalten.
&
? 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.)
&
ist ein Sonderzeichen, das bedeutet stop this command and start another one
. Ein Dateiname mit einem &
MUSS angegeben werden.
%1
... %n
und %*
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 %1
After- rem
Anweisung 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 param1
Sie sie erhalten.
param1
Aktivieren Sie die verzögerte Erweiterung, um eine sichere Verwendung zu gewährleisten.
Bearbeiten: Eine Bemerkung zu% 0
%0
enthält den Befehl zum Aufrufen des Stapels, wobei auch die Groß- / Kleinschreibung wie in FoO.BaT
Aber nach einem Aufruf einer Funktion beibehalten wird, %0
und %~0
enthält auch den Funktionsnamen (oder besser die Zeichenfolge, die zum Aufrufen der Funktion verwendet wurde).
Aber mit können %~f0
Sie 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
%~f0
Trick 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?"
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 %*
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
%%I
sich interpretieren und brechen Sie möglicherweise Ihr Skript.
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
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
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
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)
Sie können For
Commad 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.
@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 )
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
)
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.