Muszę przekazać identyfikator i hasło do pliku wsadowego podczas uruchamiania, a nie zakodować je na stałe w pliku.
Oto jak wygląda linia poleceń:
test.cmd admin P@55w0rd > test-log.txt
Muszę przekazać identyfikator i hasło do pliku wsadowego podczas uruchamiania, a nie zakodować je na stałe w pliku.
Oto jak wygląda linia poleceń:
test.cmd admin P@55w0rd > test-log.txt
Odpowiedzi:
Inną przydatną wskazówką jest użycie słowa %*„wszystko”. Na przykład:
echo off
set arg1=%1
set arg2=%2
shift
shift
fake-command /u %arg1% /p %arg2% %*
Kiedy biegniesz:
test-command admin password foo bar
powyższy plik wsadowy zostanie uruchomiony:
fake-command /u admin /p password admin password foo bar
Mogę mieć nieco niepoprawną składnię, ale taka jest ogólna idea.
shift„wyskakuje” argument z listy. Założeniem OP było %*wyprowadzenie tylko pozostałych argumentów, ale to nie działa w ten sposób, jak powiedział @Joey.
fake-command /u admin /p password admin password foo bar. Zwrócił na to uwagę @Joey wiele lat temu.
Oto jak to zrobiłem:
@fake-command /u %1 /p %2
Oto jak wygląda polecenie:
test.cmd admin P@55w0rd > test-log.txt
%1Odnosi się do pierwszego parametru na %2(i tu jest częścią trudne) odnosi się do drugiego. W ten sposób można przekazać do 9 parametrów.
echo %1 %2i był odtrącony przez niemożliwą do wycięcia i wklejenia najprostszą skrzynkę z @ai fake-commandz parametrami, myśląc, że dostaniemy fake-command.batzawartość później (w takim przypadku zbyt skomplikowane fake-command.batmoże być echo %2 %4konieczne zignorowanie nazw parametrów). Źle, doofus. TL; DR: Nie bądź taki głupi jak ja. 1. echo echo %1 %2 > test.bat2 test word1 word2.. 3. Zysk.
Jeśli chcesz inteligentnie obsłużyć brakujące parametry, możesz zrobić coś takiego:
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
Dostęp do parametrów wsadowych może być prosty za pomocą% 1,% 2, ...% 9 lub również% *,
ale tylko jeśli zawartość jest prosta.
Nie ma prostego sposobu na złożone treści, takie jak "&"^&, ponieważ nie można uzyskać dostępu do% 1 bez spowodowania błędu.
set var=%1
set "var=%1"
set var=%~1
set "var=%~1"
Linie rozwijają się do
set var="&"&
set "var="&"&"
set var="&"&
set "var="&"&"
I każdy wiersz kończy się niepowodzeniem, ponieważ jeden z nich &znajduje się poza cytatami.
Można to rozwiązać poprzez odczytanie z pliku tymczasowego zaznaczonej wersji parametru.
@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!'
Sztuką jest włączenie echo oni rozwinięcie% 1 po reminstrukcji (działa również z %2 .. %*).
Tak więc "&"&można nawet powtórzyć bez powodowania błędu, jak to zauważono.
Ale aby móc przekierować wyjście echo on, potrzebujesz dwóch pętli for.
Dodatkowe znaki * #są używane, aby zabezpieczyć się przed takimi treściami, jak /?(pokaże pomoc REM).
Lub karetka ^ na końcu linii może działać jako znak wielowierszowy, nawet po rem.
Następnie odczytaj dane wyjściowe parametru rem z pliku, ale ostrożnie.
FOR / F powinien działać z wyłączonym opóźnionym rozszerzaniem, w przeciwnym razie zawartość „!” zostanie zniszczony.
Po usunięciu dodatkowych znaków param1masz go.
Aby używać param1w bezpieczny sposób, włącz opóźnioną ekspansję.
&, twoje rozwiązanie działa tylko z prostą zawartością
test.bat ^&i nie działa. test.bat "&"Działa tylko , ale nie o to mi chodziło. Nie można używać %*, %1w sposób bezpieczny, bez techniki REM
&handlowe i cytaty"
Tak, i po prostu nie zapomnij użyć zmiennych, takich jak %%1podczas używania ifi fori gangu.
Jeśli zapomnisz podwójnego %, będziesz zastępował argumenty wiersza poleceń (być może zerowym) i będziesz otrzymywać dość mylące komunikaty o błędach.
ifi for?
for %%d in (*) do echo %%dz wiersza poleceń:for %d in (*) do echo %d
@for %%2 in (testing) do @echo %%2 %1w pliku wsadowym, powstaje, testing 1gdy zostanie wywołany za pomocą 1 ( test 1).
%%1nie ma dostępu do argumentu wiersza poleceń i jest również niepoprawny dla IFpolecenia. Tylko FORpolecenie (w plikach wsadowych) wymaga podwójnych procentów, ale nawet wtedy %%1zdefiniowałoby parametr FOR i nie ma dostępu do argumentów
Nie trzeba tego komplikować. Jest to po prostu polecenie% 1% 2 parametrów, na przykład
@echo off
xcopy %1 %2 /D /E /C /Q /H /R /K /Y /Z
echo copied %1 to %2
pause
„Pauza” pokazuje, co zrobił plik wsadowy i czeka na naciśnięcie DOWOLNEGO klawisza. Zapisz to jako xx.bat w folderze Windows.
Aby go użyć, wpisz na przykład:
xx c:\f\30\*.* f:\sites\30
Ten plik wsadowy dba o wszystkie niezbędne parametry, takie jak kopiowanie tylko plików, które są nowsze itp. Używałem go wcześniej niż system Windows. Jeśli chcesz zobaczyć nazwy plików podczas ich kopiowania, pomiń Qparametr.
Znajomy pytał mnie ostatnio o ten temat, więc pomyślałem, że opublikuję, jak radzę sobie z argumentami wiersza poleceń w plikach wsadowych.
Ta technika ma trochę narzutu, jak zobaczysz, ale sprawia, że moje pliki wsadowe są bardzo łatwe do zrozumienia i szybkiego wdrożenia. Oprócz wspierania następujących struktur:
>template.bat [-f] [--flag] [/f] [--namedvalue value] arg1 [arg2][arg3][...]
Jist z nich jest posiadanie :init, :parseoraz :mainfunkcje.
Przykładowe użycie
>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
Uwaga: JEŻELI "%1"==""spowoduje problemy, jeśli %1jest zawarte w samych cytatach.
W takim przypadku użyj IF [%1]==[]lub, w NT 4 (SP6) i tylko później IF "%~1"=="".
Uprośćmy to.
Oto plik .cmd.
@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%
Oto 3 połączenia z wiersza poleceń.
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
)
Powoduje to zapętlenie parametrów wsadowych (% *), które są cytowane lub nie, a następnie echa każdego parametru.
test.bat *.txt, test.bat cat^&doglubTest.bat /?
Napisałem prosty skrypt read_params, który można wywołać jako funkcję (lub zewnętrznie .bat) i umieści wszystkie zmienne w bieżącym środowisku. Nie zmodyfikuje oryginalnych parametrów, ponieważ funkcja jest edytowana callz kopią oryginalnych parametrów.
Na przykład, biorąc pod uwagę następujące polecenie:
myscript.bat some -random=43 extra -greeting="hello world" fluff
myscript.bat będzie mógł używać zmiennych po wywołaniu funkcji:
call :read_params %*
echo %random%
echo %greeting%
Oto funkcja:
: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
Ograniczenia
-force. Możesz użyć, -force=trueale nie mogę wymyślić sposobu, aby zezwolić na puste wartości bez znajomości listy parametrów, które nie będą miały wartości.Dziennik zmian
-parametrów przed.W pliku wsadowym
set argument1=%1
set argument2=%2
echo %argument1%
echo %argument2%
% 1 i% 2 zwracają odpowiednio pierwszy i drugi argument.
A w wierszu poleceń podaj argument
Directory> batchFileName admin P@55w0rd
Wyjście będzie
admin
P@55w0rd
Zainspirowany odpowiedzią @Jon opracowałem bardziej ogólny algorytm do wyodrębniania nazwanych parametrów, wartości opcjonalnych i przełączników.
Powiedzmy, że chcemy wdrożyć narzędzie foobar. Wymaga początkowego polecenia. Ma opcjonalny parametr, --fooktóry przyjmuje opcjonalną wartość (która oczywiście nie może być innym parametrem); jeśli brakuje wartości, domyślnie jest to default. Ma również opcjonalny parametr, --barktóry przyjmuje wymaganą wartość. Wreszcie może wziąć flagę --bazbez dozwolonej wartości. Aha, i te parametry mogą występować w dowolnej kolejności.
Innymi słowy, wygląda to tak:
foobar <command> [--foo [<fooval>]] [--bar <barval>] [--baz]
Oto rozwiązanie:
@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
SETLOCALaby zmienne nie uciekały do środowiska wywołującego.SET FOO=itp. Na wypadek, gdyby ktoś zdefiniował je w środowisku wywołującym.%~1do usuwania cytatów.IF "%ARG%" == ""a nie IF [%ARG%] == []dlatego, że [i ]nie graj w ogóle z wartościami kończącymi się spacją.SHIFTznajdujesz się w IFbloku, bieżące argumenty, takie jak %~1nie są aktualizowane, ponieważ są ustalane podczas IFanalizy. Możesz użyć %~1i %~2wewnątrz IFbloku, ale byłoby to mylące, ponieważ miałeś SHIFT. Możesz umieścić SHIFTkoniec na końcu bloku dla jasności, ale to może się zgubić i / lub dezorientować również ludzi. Zatem „wychwytywanie” %~1i %~1poza blokiem wydaje się najlepsze.IF NOT "%ARG:~0,2%" == "--".SHIFTgdy używasz jednego z parametrów.SET FOO=%DEFAULT_FOO%można żałować, ale alternatywą byłoby dodanie bloku IF "%FOO%" == "" SET FOO=%DEFAULT_FOO%zewnętrznego IF NOT "%ARG%" == "". Jednak ponieważ jest to nadal wewnątrz IF "%PARAM%" == "--foo"blokiem, przy czym %FOO%wartość byłaby oceniana i ustawić przed kiedykolwiek wszedł do bloku, więc nigdy nie będzie wykryć, że zarówno--foo parametr był obecny , a także , że %FOO%wartość brakowało.ECHO Missing bar value. 1>&2wysyła komunikat o błędzie do stderr.ECHO:lub jednej z odmian.Utwórz nowy plik wsadowy (przykład: openclass.bat) i zapisz ten wiersz w pliku:
java %~n1
Następnie umieść plik wsadowy, powiedzmy, w folderze system32, przejdź do pliku klasy Java, kliknij prawym przyciskiem myszy, Właściwości, Otwórz za pomocą ..., a następnie znajdź plik wsadowy, wybierz go i to tyle ...
Mi to pasuje.
PS: Nie mogę znaleźć sposobu na zamknięcie okna cmd, kiedy zamykam klasę Java. Na razie...
start /wait java %~n1
Proste rozwiązanie (mimo że pytanie jest stare)
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
wynik
YourLocalPath>call "C:\Temp\test.bat" pass123
YourLocalPath>echo off
"Batch started"
"arg1 is pass123"
YourLocalPath>pause
Press any key to continue . . .
Gdzie YourLocalPath jest bieżącą ścieżką do katalogu.
Dla uproszczenia przechowuj parametr polecenia w zmiennej i używaj zmiennej do porównania.
Jest nie tylko prosty w pisaniu, ale również łatwy w utrzymaniu, więc jeśli później ktoś inny lub po dłuższym czasie przeczytasz skrypt, będzie on łatwy do zrozumienia i utrzymania.
Aby napisać kod inline: zobacz inne odpowiedzi.
Aby użyć pętli, pobierz wszystkie argumenty w czystej partii:
Obs: Do użytku bez:?*&<>
@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
Twój kod jest gotowy do zrobienia czegoś z numerem argumentu, w którym potrzebuje, na przykład ...
@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
?*&<>