Ich muss zum Zeitpunkt der Ausführung eine ID und ein Kennwort an eine Batchdatei übergeben, anstatt sie fest in die Datei zu codieren.
So sieht die Befehlszeile aus:
test.cmd admin P@55w0rd > test-log.txt
Ich muss zum Zeitpunkt der Ausführung eine ID und ein Kennwort an eine Batchdatei übergeben, anstatt sie fest in die Datei zu codieren.
So sieht die Befehlszeile aus:
test.cmd admin P@55w0rd > test-log.txt
Antworten:
Ein weiterer nützlicher Tipp ist %*
"alle". 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 Batch-Datei wird ausgeführt:
fake-command /u admin /p password admin password foo bar
Ich kann die Syntax etwas falsch haben, aber das ist die allgemeine Idee.
shift
"knallt" das Argument aus der Liste. Die Annahme von OP war, dass %*
nur die verbleibenden Argumente ausgegeben würden, aber es funktioniert nicht so, wie @Joey sagte.
fake-command /u admin /p password admin password foo bar
. Darauf hat @Joey vor vielen Jahren hingewiesen.
So habe ich es gemacht:
@fake-command /u %1 /p %2
So sieht der Befehl aus:
test.cmd admin P@55w0rd > test-log.txt
Das %1
gilt für den ersten Parameter, der %2
(und hier ist der schwierige Teil) für den zweiten. Auf diese Weise können bis zu 9 Parameter übergeben werden.
echo %1 %2
einfachsten Fall mit a @
und a fake-command
mit Params gesucht und ihn weggeworfen, weil Sie dachten, wir würden fake-command.bat
später den Inhalt bekommen (in diesem Fall der überkompliziert müssen fake-command.bat
möglicherweise echo %2 %4
die Parameternamen ignoriert werden). Falsch, doofus. TL; DR: Sei nicht so dumm wie ich. 1. echo echo %1 %2 > test.bat
2 test word1 word2
.. 3. Gewinn.
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 Stapelparameter kann mit% 1,% 2, ...% 9 oder auch% * einfach sein.
einfach sein jedoch 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 Linien erweitern sich zu
set var="&"&
set "var="&"&"
set var="&"&
set "var="&"&"
Und jede Zeile schlägt fehl, da sich eine der Zeilen &
außerhalb der Anführungszeichen befindet.
Es kann durch Lesen einer kommentierten Version des Parameters aus einer temporären Datei gelöst werden.
@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
,% 1 nach einer rem
Anweisung zu aktivieren und zu erweitern (funktioniert auch mit %2 .. %*
).
So "&"&
könnte sogar ohne Fehler wiedergegeben werden, wie es bemerkt wird.
Um jedoch die Ausgabe von umleiten zu können echo on
, benötigen Sie die beiden for-Schleifen.
Die zusätzlichen Zeichen * #
werden verwendet, um vor Inhalten wie /?
(würde die Hilfe für zeigen REM
) sicher zu sein .
Oder ein Caret ^ am Zeilenende könnte auch nach a als mehrzeiliges Zeichen fungierenrem
.
Lesen Sie dann den aus der Datei ausgegebenen rem-Parameter sorgfältig durch.
Das FOR / F sollte mit verzögerter Erweiterung funktionieren, sonst Inhalt mit "!" würde zerstört werden.
Nach dem Entfernen der zusätzlichen Zeichen inparam1
, haben Sie es bekommen.
param1
Aktivieren Sie die verzögerte Erweiterung, um eine sichere Verwendung zu gewährleisten.
&
, Ihre Lösung funktioniert nur mit einfachen Inhalten
test.bat ^&
und es schlägt fehl. Funktioniert nur test.bat "&"
, aber das war nicht mein Punkt. Sie können nicht verwenden %*
, %1
auf sichere Weise ohne die REM - Technik
&
und auch Anführungszeichen"
Ja, und vergessen Sie nicht, Variablen wie %%1
bei if
und zu verwendenfor
und die Bande zu verwenden.
Wenn Sie das Double vergessen %
, ersetzen Sie (möglicherweise null) Befehlszeilenargumente und erhalten einige ziemlich verwirrende Fehlermeldungen.
if
und for
?
for %%d in (*) do echo %%d
Von der Kommandozeile:for %d in (*) do echo %d
@for %%2 in (testing) do @echo %%2 %1
in einer Batch-Datei, erzeugt, testing 1
wenn es mit 1 ( test 1
) aufgerufen wird .
%%1
greift nicht auf ein Befehlszeilenargument zu und ist auch für den IF
Befehl falsch . Nur der FOR
Befehl (in Batch-Dateien) erfordert doppelte Prozentsätze, würde aber selbst dann %%1
einen FOR-Parameter definieren und nicht auf Argumente zugreifen
Es besteht keine Notwendigkeit, dies zu komplizieren. Es ist einfach 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 Batch-Datei getan hat, und wartet darauf, dass Sie die Taste ANY drücken. Speichern Sie das als xx.bat im Windows-Ordner.
Geben Sie dazu beispielsweise Folgendes ein:
xx c:\f\30\*.* f:\sites\30
Diese Batch-Datei kümmert sich um alle notwendigen Parameter, wie das Kopieren nur neuerer Dateien usw. Ich habe sie seit vor Windows verwendet. Wenn Sie die Namen der Dateien beim Kopieren sehen möchten, lassen Sie den Q
Parameter weg .
Ein Freund hat mich kürzlich zu diesem Thema gefragt, daher dachte ich, ich würde posten, wie ich mit Befehlszeilenargumenten in Batch-Dateien umgehe.
Wie Sie sehen werden, ist diese Technik etwas aufwändig, aber meine Batch-Dateien sind sehr einfach zu verstehen und schnell zu implementieren. Sowie Unterstützung der folgenden Strukturen:
>template.bat [-f] [--flag] [/f] [--namedvalue value] arg1 [arg2][arg3][...]
Der jist davon ist mit den :init
, :parse
und :main
Funktionen.
Anwendungsbeispiel
>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
@ECHO OFF
:Loop
IF "%1"=="" GOTO Continue
SHIFT
GOTO Loop
:Continue
Hinweis: IF "%1"==""
verursacht Probleme, wenn %1
es in Anführungszeichen eingeschlossen ist.
Verwenden Sie in diesem Fall stattdessen IF [%1]==[]
oder in NT 4 (SP6) und höher IF "%~1"==""
.
Lassen Sie uns das einfach halten.
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 Anrufe 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 Stapelparameter (% *), entweder in Anführungszeichen oder nicht, und gibt dann jeden Parameter wieder.
test.bat *.txt
, test.bat cat^&dog
oderTest.bat /?
Ich habe ein einfaches read_params-Skript geschrieben, das als Funktion (oder extern .bat
) aufgerufen werden kann und alle Variablen in die aktuelle Umgebung einfügt . Die ursprünglichen Parameter werden nicht geändert, da die Funktion ausgeführt wirdcall
mit einer Kopie der ursprünglichen Parameter bearbeitet wird.
Beispiel: Geben Sie 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
-force
. Sie könnten verwenden, -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
-
Vor-Parametern gesucht wird.Inspiriert von einer Antwort von @Jon an anderer Stelle habe ich einen allgemeineren Algorithmus zum Extrahieren benannter Parameter, optionaler Werte und Schalter entwickelt.
Nehmen wir an, wir möchten ein Dienstprogramm implementieren foobar
. Es erfordert einen ersten Befehl. Es hat einen optionalen Parameter, --foo
der einen optionalen Wert annimmt (der natürlich kein anderer Parameter sein kann). Wenn der Wert fehlt, wird standardmäßig verwendet default
. Es hat auch einen optionalen Parameter, --bar
der einen erforderlichen Wert annimmt. Schließlich kann es eine Flagge nehmen--baz
ohne zulässigen Wert verwendet werden. Oh, und diese Parameter können in beliebiger Reihenfolge kommen.
Mit anderen Worten, es sieht 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
SETLOCAL
Option, damit die Variablen nicht in die aufrufende Umgebung gelangen.SET FOO=
usw. zu initialisieren , falls jemand sie in der aufrufenden Umgebung definiert hat.%~1
diese Option , um Anführungszeichen zu entfernen.IF "%ARG%" == ""
und nicht IF [%ARG%] == []
weil [
und]
spielen Sie überhaupt nicht mit Werten, die in einem Leerzeichen enden.SHIFT
in einem IF
Block befinden, werden die aktuellen Argumente wie z. B. %~1
nicht aktualisiert, da sie bestimmt werden, wenn das IF
analysiert wird. Sie könnten %~1
und %~2
innerhalb des IF
Blocks verwenden, aber es wäre verwirrend, weil Sie eine hatten SHIFT
. Sie könnten das SHIFT
aus Gründen der Klarheit am Ende des Blocks platzieren, aber das könnte verloren gehen und / oder auch die Leute verwirren. "Erfassen" %~1
und %~1
außerhalb des Blocks scheint also am besten.IF NOT "%ARG:~0,2%" == "--"
.SHIFT
wenn Sie verwenden einen der Parameter.SET FOO=%DEFAULT_FOO%
ist bedauerlich, aber die Alternative wäre, einen IF "%FOO%" == "" SET FOO=%DEFAULT_FOO%
außerhalb des IF NOT "%ARG%" == ""
Blocks hinzuzufügen . Da sich dies jedoch noch im IF "%PARAM%" == "--foo"
Block befindet, wurde der %FOO%
Wert ausgewertet und festgelegt, bevor Sie den Block betreten haben, sodass Sie niemals feststellen würden, dass sowohl der --foo
Parameter vorhanden war als auch der %FOO%
Wert fehlte.ECHO Missing bar value. 1>&2
die Fehlermeldung an stderr gesendet wird.ECHO:
oder eine der Variationen verwenden.Erstellen Sie eine neue Batch-Datei (Beispiel: openclass.bat) und schreiben Sie diese Zeile in die Datei:
java %~n1
Legen Sie dann die Batch-Datei in den Ordner system32, wechseln Sie zu Ihrer Java-Klassendatei, klicken Sie mit der rechten Maustaste auf Eigenschaften, Öffnen mit ..., suchen Sie Ihre Batch-Datei, wählen Sie sie aus und fertig ...
Für mich geht das.
PS: Ich kann das cmd-Fenster nicht schließen, wenn ich die Java-Klasse schließe. Zur Zeit...
start /wait java %~n1
Einfache Lösung (obwohl 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 variable und verwenden Sie variable zum Vergleich.
Es ist nicht nur einfach zu schreiben, sondern auch einfach zu warten. Wenn also später eine andere Person oder Sie Ihr Skript nach langer Zeit lesen, ist es leicht zu verstehen und zu warten.
So schreiben Sie Code inline: Siehe andere Antworten.
Um Schleifen zu verwenden, erhalten Sie alle Argumente und in reinen Batch:
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_!" && for /l %%l in (!_cnt! 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_!"
)
fake-command /u !_arg_[1]! /p !_arg_[2]! > test-log.txt
?*&<>