Wie kann ich Argumente an eine Batchdatei übergeben?
-
09-06-2019 - |
Frage
Ich muss einer Batchdatei zum Zeitpunkt der Ausführung eine ID und ein Passwort übergeben, anstatt sie fest in die Datei zu codieren.
So sieht die Befehlszeile aus:
test.cmd admin P@55w0rd > test-log.txt
Lösung 2
So habe ich es gemacht:
@fake-command /u %1 /p %2
So sieht der Befehl aus:
test.cmd admin P@55w0rd > test-log.txt
Der %1
gilt für den ersten Parameter der %2
(und hier ist der knifflige Teil) gilt für den zweiten.Auf diese Weise können Sie bis zu 9 Parameter übergeben lassen.
Andere Tipps
Ein weiterer nützlicher Tipp ist die Verwendung %*
„alle“ bedeuten.Zum Beispiel:
echo off
set arg1=%1
set arg2=%2
shift
shift
fake-command /u %arg1% /p %arg2% %*
Wenn Sie laufen:
test-command admin password foo bar
Die obige Batchdatei wird ausgeführt:
fake-command /u admin /p password admin password foo bar
Möglicherweise ist die Syntax etwas falsch, aber das ist die allgemeine Idee.
Wenn Sie fehlende Parameter intelligent behandeln möchten, können Sie Folgendes tun:
IF %1.==. GOTO No1
IF %2.==. GOTO No2
... do stuff...
GOTO End1
:No1
ECHO No param 1
GOTO End1
:No2
ECHO No param 2
GOTO End1
:End1
Der Zugriff auf Batch-Parameter kann einfach sein mit %1, %2, ...%9 oder auch %*,
aber nur, wenn der Inhalt einfach ist.
Es gibt keine einfache Möglichkeit für komplexe Inhalte wie "&"^&
, da es nicht möglich ist, auf %1 zuzugreifen, ohne einen Fehler zu erzeugen.
set var=%1
set "var=%1"
set var=%~1
set "var=%~1"
Die Zeilen erweitern sich zu
set var="&"&
set "var="&"&"
set var="&"&
set "var="&"&"
Und jede Zeile schlägt fehl, da eine der &
steht außerhalb der Anführungszeichen.
Es kann durch Lesen aus einer temporären Datei gelöst werden a bemerkte Version des Parameters.
@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, es zu aktivieren echo on
und erweitern Sie %1 nach a rem
Aussage (funktioniert auch mit %2 .. %*
).
Also sogar "&"&
könnte wiederholt werden, ohne einen Fehler zu erzeugen, wie bemerkt wird.
Aber um die Ausgabe des umleiten zu können echo on
, benötigen Sie die beiden for-Schleifen.
Die zusätzlichen Zeichen * #
werden verwendet, um vor Inhalten wie z /?
(würde die Hilfe für anzeigen REM
).
Oder ein Caretzeichen ^ am Zeilenende könnte als mehrzeiliges Zeichen funktionieren, auch nach einem rem
.
Dann lesen Sie die rem-Parameter Ausgabe aus der Datei, aber sorgfältig.
Die für /f sollte mit einer verzögerten Expansion arbeiten, sonst Inhalt mit "!" würde zerstört werden.
Nach dem Entfernen der zusätzlichen Zeichen in param1
, du hast es.
Und zu nutzen param1
ermöglichen Sie auf sichere Weise die verzögerte Erweiterung.
Ja, und vergessen Sie nicht, Variablen wie zu verwenden %%1
beim Benutzen if
Und for
und die Bande.
Wenn Sie das Double vergessen %
, dann ersetzen Sie (möglicherweise null) Befehlszeilenargumente und erhalten einige ziemlich verwirrende Fehlermeldungen.
Es besteht kein Grund, es zu komplizieren.Es handelt sich einfach um den Befehl %1 %2 Parameter, zum Beispiel:
@echo off
xcopy %1 %2 /D /E /C /Q /H /R /K /Y /Z
echo copied %1 to %2
pause
Die „Pause“ zeigt an, was die Batchdatei getan hat, und wartet darauf, dass Sie die Taste ANY drücken.Speichern Sie das als xx.bat im Windows-Ordner.
Um es zu verwenden, geben Sie zum Beispiel Folgendes ein:
xx c:\f\30\*.* f:\sites\30
Diese Batchdatei kümmert sich um alle notwendigen Parameter, wie z. B. das Kopieren nur neuerer Dateien usw.Ich habe es schon vor Windows verwendet.Wenn Sie die Namen der Dateien beim Kopieren sehen möchten, lassen Sie das weg Q
Parameter.
@ECHO OFF
:Loop
IF "%1"=="" GOTO Continue
SHIFT
GOTO Loop
:Continue
Notiz:WENN "%1"==""
wird Probleme verursachen, wenn %1
wird selbst in Anführungszeichen gesetzt.
In diesem Fall verwenden Sie IF [%1]==[]
oder, nur in NT 4 (SP6) und höher, IF "%~1"==""
stattdessen.
Ein Freund hat mich kürzlich zu diesem Thema gefragt, also dachte ich, ich poste mal, wie ich mit Befehlszeilenargumenten in Batchdateien umgehe.
Wie Sie sehen werden, verursacht diese Technik einen gewissen Mehraufwand, aber sie macht meine Batch-Dateien sehr einfach zu verstehen und schnell zu implementieren.Darüber hinaus unterstützen wir folgende Strukturen:
>template.bat [-f] [--flag] [/f] [--namedvalue value] arg1 [arg2][arg3][...]
Das Wesentliche daran ist, das zu haben :init
, :parse
, Und :main
Funktionen.
Beispielverwendung
>template.bat /?
test v1.23
This is a sample batch file template,
providing command-line arguments and flags.
USAGE:
test.bat [flags] "required argument" "optional argument"
/?, --help shows this help
/v, --version shows the version
/e, --verbose shows detailed output
-f, --flag value specifies a named parameter value
>template.bat <- throws missing argument error
(same as /?, plus..)
**** ****
**** MISSING "REQUIRED ARGUMENT" ****
**** ****
>template.bat -v
1.23
>template.bat --version
test v1.23
This is a sample batch file template,
providing command-line arguments and flags.
>template.bat -e arg1
**** DEBUG IS ON
UnNamedArgument: "arg1"
UnNamedOptionalArg: not provided
NamedFlag: not provided
>template.bat --flag "my flag" arg1 arg2
UnNamedArgument: "arg1"
UnNamedOptionalArg: "arg2"
NamedFlag: "my flag"
>template.bat --verbose "argument #1" --flag "my flag" second
**** DEBUG IS ON
UnNamedArgument: "argument #1"
UnNamedOptionalArg: "second"
NamedFlag: "my flag"
template.bat
@::!/dos/rocks
@echo off
goto :init
:header
echo %__NAME% v%__VERSION%
echo This is a sample batch file template,
echo providing command-line arguments and flags.
echo.
goto :eof
:usage
echo USAGE:
echo %__BAT_NAME% [flags] "required argument" "optional argument"
echo.
echo. /?, --help shows this help
echo. /v, --version shows the version
echo. /e, --verbose shows detailed output
echo. -f, --flag value specifies a named parameter value
goto :eof
:version
if "%~1"=="full" call :header & goto :eof
echo %__VERSION%
goto :eof
:missing_argument
call :header
call :usage
echo.
echo **** ****
echo **** MISSING "REQUIRED ARGUMENT" ****
echo **** ****
echo.
goto :eof
:init
set "__NAME=%~n0"
set "__VERSION=1.23"
set "__YEAR=2017"
set "__BAT_FILE=%~0"
set "__BAT_PATH=%~dp0"
set "__BAT_NAME=%~nx0"
set "OptHelp="
set "OptVersion="
set "OptVerbose="
set "UnNamedArgument="
set "UnNamedOptionalArg="
set "NamedFlag="
:parse
if "%~1"=="" goto :validate
if /i "%~1"=="/?" call :header & call :usage "%~2" & goto :end
if /i "%~1"=="-?" call :header & call :usage "%~2" & goto :end
if /i "%~1"=="--help" call :header & call :usage "%~2" & goto :end
if /i "%~1"=="/v" call :version & goto :end
if /i "%~1"=="-v" call :version & goto :end
if /i "%~1"=="--version" call :version full & goto :end
if /i "%~1"=="/e" set "OptVerbose=yes" & shift & goto :parse
if /i "%~1"=="-e" set "OptVerbose=yes" & shift & goto :parse
if /i "%~1"=="--verbose" set "OptVerbose=yes" & shift & goto :parse
if /i "%~1"=="--flag" set "NamedFlag=%~2" & shift & shift & goto :parse
if not defined UnNamedArgument set "UnNamedArgument=%~1" & shift & goto :parse
if not defined UnNamedOptionalArg set "UnNamedOptionalArg=%~1" & shift & goto :parse
shift
goto :parse
:validate
if not defined UnNamedArgument call :missing_argument & goto :end
:main
if defined OptVerbose (
echo **** DEBUG IS ON
)
echo UnNamedArgument: "%UnNamedArgument%"
if defined UnNamedOptionalArg echo UnNamedOptionalArg: "%UnNamedOptionalArg%"
if not defined UnNamedOptionalArg echo UnNamedOptionalArg: not provided
if defined NamedFlag echo NamedFlag: "%NamedFlag%"
if not defined NamedFlag echo NamedFlag: not provided
:end
call :cleanup
exit /B
:cleanup
REM The cleanup function is only really necessary if you
REM are _not_ using SETLOCAL.
set "__NAME="
set "__VERSION="
set "__YEAR="
set "__BAT_FILE="
set "__BAT_PATH="
set "__BAT_NAME="
set "OptHelp="
set "OptVersion="
set "OptVerbose="
set "UnNamedArgument="
set "UnNamedArgument2="
set "NamedFlag="
goto :eof
Halten wir es einfach.
Hier ist die .cmd-Datei.
@echo off
rem this file is named echo_3params.cmd
echo %1
echo %2
echo %3
set v1=%1
set v2=%2
set v3=%3
echo v1 equals %v1%
echo v2 equals %v2%
echo v3 equals %v3%
Hier sind 3 Aufrufe von der Kommandozeile.
C:\Users\joeco>echo_3params 1abc 2 def 3 ghi
1abc
2
def
v1 equals 1abc
v2 equals 2
v3 equals def
C:\Users\joeco>echo_3params 1abc "2 def" "3 ghi"
1abc
"2 def"
"3 ghi"
v1 equals 1abc
v2 equals "2 def"
v3 equals "3 ghi"
C:\Users\joeco>echo_3params 1abc '2 def' "3 ghi"
1abc
'2
def'
v1 equals 1abc
v2 equals '2
v3 equals def'
C:\Users\joeco>
FOR %%A IN (%*) DO (
REM Now your batch file handles %%A instead of %1
REM No need to use SHIFT anymore.
ECHO %%A
)
Dies durchläuft die Batch-Parameter (%*), unabhängig davon, ob sie in Anführungszeichen stehen oder nicht, und gibt dann jeden Parameter zurück.
Ich habe ein einfaches read_params-Skript geschrieben, das als Funktion (oder extern) aufgerufen werden kann .bat
) und fügt alle Variablen in die aktuelle Umgebung ein.Die ursprünglichen Parameter werden nicht geändert, da die Funktion ausgeführt wird call
mit einer Kopie der Originalparameter versehen.
Geben Sie beispielsweise den folgenden Befehl ein:
myscript.bat some -random=43 extra -greeting="hello world" fluff
myscript.bat
könnte die Variablen nach dem Aufruf der Funktion verwenden:
call :read_params %*
echo %random%
echo %greeting%
Hier ist die Funktion:
:read_params
if not %1/==/ (
if not "%__var%"=="" (
if not "%__var:~0,1%"=="-" (
endlocal
goto read_params
)
endlocal & set %__var:~1%=%~1
) else (
setlocal & set __var=%~1
)
shift
goto read_params
)
exit /B
Einschränkungen
- Argumente ohne Wert können nicht geladen werden, z. B
-force
.Du könntest benutzen-force=true
Aber ich kann mir keine Möglichkeit vorstellen, leere Werte zuzulassen, ohne vorher eine Liste von Parametern zu kennen, die keinen Wert haben.
Änderungsprotokoll
- 2/18/2016
- Erfordert keine verzögerte Erweiterung mehr
- Funktioniert jetzt mit anderen Befehlszeilenargumenten, indem nach gesucht wird
-
vor Parametern.
Um auf eine festgelegte Variable in der Befehlszeile zu verweisen, müssten Sie verwenden %a%
also zum Beispiel:
set a=100
echo %a%
rem output = 100
Notiz:Dies funktioniert für Windows 7 Pro.
Erstellen Sie eine neue Batchdatei (Beispiel:openclass.bat) und schreiben Sie diese Zeile in die Datei:
java %~n1
Platzieren Sie dann die Batch-Datei beispielsweise im Ordner system32, gehen Sie zu Ihrer Java-Klassendatei, klicken Sie mit der rechten Maustaste, Eigenschaften, Öffnen mit..., suchen Sie dann Ihre Batch-Datei, wählen Sie sie aus und fertig...
Für mich geht das.
PS:Ich kann keine Möglichkeit finden, das cmd-Fenster zu schließen, wenn ich die Java-Klasse schließe.Zur Zeit...
Inspiriert von einem woanders antworten von @Jon, ich habe einen allgemeineren Algorithmus zum Extrahieren benannter Parameter, optionaler Werte und Schalter erstellt.
Nehmen wir an, wir möchten ein Dienstprogramm implementieren foobar
.Es erfordert einen ersten Befehl.Es verfügt über einen optionalen Parameter --foo
Das dauert eine Optional Wert (der natürlich kein anderer Parameter sein kann);Wenn der Wert fehlt, wird standardmäßig verwendet default
.Es gibt auch einen optionalen Parameter --bar
Das dauert eine erforderlich Wert.Schließlich kann es eine Flagge vertragen --baz
ohne zulässigen Wert.Oh, und diese Parameter können in beliebiger Reihenfolge vorliegen.
Mit anderen Worten sieht es so aus:
foobar <command> [--foo [<fooval>]] [--bar <barval>] [--baz]
Hier ist eine Lösung:
@ECHO OFF
SETLOCAL
REM FooBar parameter demo
REM By Garret Wilson
SET CMD=%~1
IF "%CMD%" == "" (
GOTO usage
)
SET FOO=
SET DEFAULT_FOO=default
SET BAR=
SET BAZ=
SHIFT
:args
SET PARAM=%~1
SET ARG=%~2
IF "%PARAM%" == "--foo" (
SHIFT
IF NOT "%ARG%" == "" (
IF NOT "%ARG:~0,2%" == "--" (
SET FOO=%ARG%
SHIFT
) ELSE (
SET FOO=%DEFAULT_FOO%
)
) ELSE (
SET FOO=%DEFAULT_FOO%
)
) ELSE IF "%PARAM%" == "--bar" (
SHIFT
IF NOT "%ARG%" == "" (
SET BAR=%ARG%
SHIFT
) ELSE (
ECHO Missing bar value. 1>&2
ECHO:
GOTO usage
)
) ELSE IF "%PARAM%" == "--baz" (
SHIFT
SET BAZ=true
) ELSE IF "%PARAM%" == "" (
GOTO endargs
) ELSE (
ECHO Unrecognized option %1. 1>&2
ECHO:
GOTO usage
)
GOTO args
:endargs
ECHO Command: %CMD%
IF NOT "%FOO%" == "" (
ECHO Foo: %FOO%
)
IF NOT "%BAR%" == "" (
ECHO Bar: %BAR%
)
IF "%BAZ%" == "true" (
ECHO Baz
)
REM TODO do something with FOO, BAR, and/or BAZ
GOTO :eof
:usage
ECHO FooBar
ECHO Usage: foobar ^<command^> [--foo [^<fooval^>]] [--bar ^<barval^>] [--baz]
EXIT /B 1
- Verwenden
SETLOCAL
damit die Variablen nicht in die aufrufende Umgebung gelangen. - Vergessen Sie nicht, die Variablen zu initialisieren
SET FOO=
, usw.für den Fall, dass jemand sie in der aufrufenden Umgebung definiert hat. - Verwenden
%~1
um Anführungszeichen zu entfernen. - Verwenden
IF "%ARG%" == ""
und nichtIF [%ARG%] == []
Weil[
Und]
Spielen Sie überhaupt nicht mit Werten, die mit einem Leerzeichen enden. - Auch wenn Du
SHIFT
innerhalb einerIF
Block, die aktuellen Argumente wie z%~1
werden nicht aktualisiert, da sie bestimmt werden, wann dieIF
wird analysiert.Du könntest benutzen%~1
Und%~2
im InnerenIF
Block, aber es wäre verwirrend, weil Sie einen hattenSHIFT
.Du könntest das sagenSHIFT
aus Gründen der Klarheit am Ende des Blocks, aber das könnte verloren gehen und/oder die Leute auch verwirren.Also „einfangen“%~1
Und%~1
außerhalb des Blocks scheint am besten zu sein. - Sie möchten einen Parameter nicht anstelle des optionalen Werts eines anderen Parameters verwenden, also müssen Sie dies überprüfen
IF NOT "%ARG:~0,2%" == "--"
. - Achten Sie nur darauf
SHIFT
wenn du verwenden einer der Parameter. - Der doppelte Code
SET FOO=%DEFAULT_FOO%
ist bedauerlich, aber die Alternative wäre, eine hinzuzufügenIF "%FOO%" == "" SET FOO=%DEFAULT_FOO%
außerhalb vonIF NOT "%ARG%" == ""
Block.Da sich dies jedoch immer noch im Inneren befindetIF "%PARAM%" == "--foo"
Block, der%FOO%
Der Wert wäre ausgewertet und festgelegt worden, bevor Sie den Block betreten hätten, sodass Sie das nie bemerken würden beide Die--foo
Parameter vorhanden war und auch dass die%FOO%
Wert fehlte. - Beachten Sie, dass
ECHO Missing bar value. 1>&2
sendet die Fehlermeldung an stderr. - Möchten Sie eine Leerzeile in einer Windows-Batchdatei?Du musst es benutzen
ECHO:
oder eine der Variationen.
Einfache Lösung (auch wenn die Frage alt ist)
Test1.bat
echo off
echo "Batch started"
set arg1=%1
echo "arg1 is %arg1%"
echo on
pause
CallTest1.bat
call "C:\Temp\Test1.bat" pass123
Ausgabe
YourLocalPath>call "C:\Temp\test.bat" pass123
YourLocalPath>echo off
"Batch started"
"arg1 is pass123"
YourLocalPath>pause
Press any key to continue . . .
Wobei YourLocalPath der aktuelle Verzeichnispfad ist.
Um die Dinge einfach zu halten, speichern Sie den Befehlsparameter in einer Variablen und verwenden Sie die Variable zum Vergleich.
Es ist nicht nur einfach zu schreiben, sondern auch einfach zu warten. Wenn also später jemand anderes oder Sie Ihr Skript nach längerer Zeit lesen, ist es leicht zu verstehen und zu pflegen.
So schreiben Sie Code inline:siehe andere Antworten.
Um eine Schleife zu verwenden, erhalten Sie alle Argumente und im reinen Batch:
@echo off && setlocal EnableDelayedExpansion
set "_cnt=0" && for %%Z in (%*) do (
set "_arg_=%%Z" && set /a "_cnt=!_cnt! + 1" && set "_arg_[!_cnt!]=!_arg_!"
shift && for /l %%l in (!_cnt! 1 !_cnt!) do echo/ The argument n:%%l is: !_arg_[%%l]!
)
goto :eof
Ihr Code ist bereit, mit der Argumentnummer dort etwas zu tun, wo er benötigt wird, z. B. ...
@echo off && setlocal EnableDelayedExpansion
set "_cnt=0" && for %%Z in (%*) do (
set "_arg_=%%Z" && set /a "_cnt=!_cnt! + 1" && set "_arg_[!_cnt!]=!_arg_!"
shift
)
fake-command /u !_arg_[1]! /p !_arg_[2]! > test-log.txt