Ben bir toplu iş dosyası yerine hardcoding onları yerine bir toplu iş dosyasına bir kimlik ve parola geçmek gerekir.
Komut satırı şöyle görünür:
test.cmd admin P@55w0rd > test-log.txt
Ben bir toplu iş dosyası yerine hardcoding onları yerine bir toplu iş dosyasına bir kimlik ve parola geçmek gerekir.
Komut satırı şöyle görünür:
test.cmd admin P@55w0rd > test-log.txt
Yanıtlar:
Bir başka yararlı ipucu da %*
"hepsi" anlamına gelmektir. Örneğin:
echo off
set arg1=%1
set arg2=%2
shift
shift
fake-command /u %arg1% /p %arg2% %*
Koştuğunuzda:
test-command admin password foo bar
yukarıdaki toplu iş dosyası çalışır:
fake-command /u admin /p password admin password foo bar
Sözdizimi biraz yanlış olabilir, ama genel fikir budur.
shift
listeden argümanı "açıyor". OP'nin varsayımı %*
, sadece kalan argümanların çıktısını alacaktı, ancak @Joey'in dediği gibi bu şekilde çalışmaz.
fake-command /u admin /p password admin password foo bar
. Bu, yıllar önce @Joey tarafından işaret edildi.
İşte böyle yaptım:
@fake-command /u %1 /p %2
Komut şöyle görünür:
test.cmd admin P@55w0rd > test-log.txt
Uygulamanın %1
ilk parametresi için geçerlidir %2
(ve işte zor kısım) ikincisine uygulanır. Bu şekilde en fazla 9 parametrenin geçirilmesini sağlayabilirsiniz.
echo %1 %2
aptalsan, zihnin , daha sonra içeriğini alacağımızı düşünerek, a @
ve a fake-command
ile para-kesik ve kesilemez basit vaka tarafından arandı ve atıldı fake-command.bat
(bu durumda, aşırı karmaşık param adlarını göz ardı etmek zorunda fake-command.bat
kalabilir echo %2 %4
). Yanlış, doofus. TL; DR: Benim kadar aptal olma. 1. echo echo %1 %2 > test.bat
2. test word1 word2
. 3. Kâr.
Eksik parametreleri akıllıca işlemek istiyorsanız, aşağıdakileri yapabilirsiniz:
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
% 1,% 2, ...% 9 veya% * ile toplu iş parametrelerine erişim basit olabilir,
ancak yalnızca içerik basitse.
"&"^&
Hata oluşturmadan% 1'e erişmek mümkün olmadığından, karmaşık içerikler için basit bir yol yoktur .
set var=%1
set "var=%1"
set var=%~1
set "var=%~1"
Çizgiler
set var="&"&
set "var="&"&"
set var="&"&
set "var="&"&"
Ve her satır başarısız, biri &
tırnak dışında.
Bu geçici dosyasından bir okuma ile çözülebilir söylediği parametrenin sürümünü.
@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!'
Hile, echo on
bir rem
ifadeden sonra% 1'i etkinleştirmek ve genişletmektir (ayrıca çalışır %2 .. %*
).
Bu yüzden "&"&
, belirtildiği gibi, bir hata üretmeden bile yankılanabilirdi.
Ancak, çıktısını yeniden yönlendirebilmek echo on
için iki döngüye ihtiyacınız vardır.
Ekstra karakterler * #
, gibi içeriklere karşı güvenli olmak için kullanılır /?
(yardımını gösterir REM
).
Veya satır sonundaki bir şapka karakteri ^, a karakterinden sonra bile çok satırlı bir karakter olarak çalışabilir rem
.
Sonra dosyadan rem parametre çıktısını, ancak dikkatlice okuyun.
FOR / F gecikmeli genişleme kapalı, diğer içerikler "!" yok olur.
Ekstra karakterleri çıkardıktan sonra anladınız param1
.
param1
Güvenli bir şekilde kullanmak için, gecikmeli genişletmeyi etkinleştirin.
&
, çözümünüz yalnızca basit içerikle çalışır
test.bat ^&
ve başarısız oldu. Sadece test.bat "&"
işe yarıyor, ama benim amacım bu değildi. Sen kullanamaz %*
, %1
REM tekniği olmadan güvenli şekilde
&
ve işaretleri ve tırnak içerir"
Evet, ve tıpkı değişkenleri kullanmak unutmayın %%1
kullanırken if
ve for
çete ve.
Çifti unutursanız, %
(muhtemelen null) komut satırı argümanlarını değiştireceksiniz ve oldukça kafa karıştırıcı bazı hata mesajları alacaksınız.
if
ve for
?
for %%d in (*) do echo %%d
komut satırından:for %d in (*) do echo %d
@for %%2 in (testing) do @echo %%2 %1
bir toplu iş dosyasında, testing 1
1 ( test 1
) ile çağrıldığında üretilir .
%%1
bir komut satırı bağımsız değişkenine erişmez ve IF
komut için de yanlıştır . Yalnızca FOR
komut (toplu iş dosyalarında) çift yüzdelik gerektirir, ancak o %%1
zaman bile bir FOR parametresi tanımlar ve bağımsız değişkenlere
Bunu karmaşıklaştırmaya gerek yok. Bu sadece% 1% 2 parametrelerini kumanda eder, örneğin,
@echo off
xcopy %1 %2 /D /E /C /Q /H /R /K /Y /Z
echo copied %1 to %2
pause
"Duraklat", toplu iş dosyasının ne yaptığını görüntüler ve HERHANGİ BİR tuşa basmanızı bekler. Bunu Windows klasörüne xx.bat olarak kaydedin.
Kullanmak için şunu yazın, örneğin:
xx c:\f\30\*.* f:\sites\30
Bu toplu iş dosyası, yalnızca daha yeni olan dosyaları kopyalama gibi gerekli tüm parametreleri dikkate alır. Windows'tan beri kullanıyorum. Dosyaların kopyalandıkça adlarını görmek isterseniz, Q
parametreyi dışarıda bırakın .
Yakın zamanda bir arkadaşım bana bu konuyu soruyordu, bu yüzden toplu iş dosyalarında komut satırı argümanlarını nasıl ele aldığımı yayınlayacağımı düşündüm.
Bu tekniğin göreceğiniz gibi biraz ek yükü var, ancak toplu iş dosyalarımı çok kolay ve hızlı bir şekilde uyguluyor. Aşağıdaki yapıları desteklemenin yanı sıra:
>template.bat [-f] [--flag] [/f] [--namedvalue value] arg1 [arg2][arg3][...]
Bunun jist yaşıyor :init
, :parse
ve :main
işlevleri.
Örnek kullanım
>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
Not: IF "%1"==""
, %1
tırnak içine alınmışsa sorunlara neden olur .
Bu durumda IF [%1]==[]
, IF "%~1"==""
bunun yerine yalnızca NT 4 (SP6) ve sonraki sürümlerinde veya kullanın.
Bunu basit tutalım.
İşte .cmd dosyası.
@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%
İşte komut satırından 3 çağrı.
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
)
Bu, toplu parametreler (% *) üzerinden alıntılanır veya alıntılanmaz, sonra her parametreyi yansıtır.
test.bat *.txt
, test.bat cat^&dog
yaTest.bat /?
Bir işlev (veya harici .bat
) olarak adlandırılabilir ve tüm değişkenleri geçerli ortama koyacağız basit bir read_params komut dosyası yazdım . İşlev orijinal parametrelerin call
bir kopyasıyla düzenlendiği için orijinal parametreleri değiştirmez.
Örneğin, aşağıdaki komut verildiğinde:
myscript.bat some -random=43 extra -greeting="hello world" fluff
myscript.bat
işlevi çağırdıktan sonra değişkenleri kullanabilecektir:
call :read_params %*
echo %random%
echo %greeting%
İşte işlevi:
: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
Sınırlamalar
-force
. Kullanabilirsiniz, -force=true
ancak bir değere sahip olmayacak bir parametre listesini bilmeden boş değerlere izin vermenin bir yolunu düşünemiyorum.Değişiklikler
-
parametrelerden önce bakarak diğer komut satırı bağımsız değişkenleriyle çalışır .Toplu iş dosyasında
set argument1=%1
set argument2=%2
echo %argument1%
echo %argument2%
% 1 ve% 2 sırasıyla birinci ve ikinci bağımsız değişken değerlerini döndürür.
Ve komut satırında, tartışmayı geç
Directory> batchFileName admin P@55w0rd
Çıktı
admin
P@55w0rd
@Jon tarafından başka bir cevaptan esinlenerek , adlandırılmış parametreleri, isteğe bağlı değerleri ve anahtarları çıkarmak için daha genel bir algoritma hazırladım.
Bir yardımcı program uygulamak istediğimizi söyleyelim foobar
. Bir başlangıç komutu gerektirir. İsteğe bağlı bir değer --foo
alan isteğe bağlı bir parametreye sahiptir (elbette başka bir parametre olamaz); değer eksikse varsayılan değerdir . Ayrıca, gerekli bir değeri alan isteğe bağlı bir parametreye sahiptir . Son olarak , hiçbir değere izin verilmeyen bir bayrak alabilir . Oh, ve bu parametreler herhangi bir sırada gelebilir.default
--bar
--baz
Başka bir deyişle, şöyle görünür:
foobar <command> [--foo [<fooval>]] [--bar <barval>] [--baz]
İşte bir çözüm:
@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
Değişkenlerin çağrı ortamına kaçmaması için kullanın .SET FOO=
Birinin çağrı ortamında tanımlaması durumunda değişkenleri , vb. Başlatmayı unutmayın .%~1
Tırnak işaretlerini kaldırmak için kullanın .IF "%ARG%" == ""
ve IF [%ARG%] == []
çünkü [
ve ]
bir boşluk biten değerlerle hiç iradeyi oynamaz.SHIFT
Bir IF
bloğun içinde olsanız bile , gibi geçerli argümanlar %~1
güncellenmez çünkü IF
ayrıştırıldığında belirlenir . Bloğun içinde %~1
ve %~2
içinde kullanabilirsiniz IF
, ancak kafa karıştırıcı olurdu çünkü bir SHIFT
. SHIFT
Açıklık için bloğun sonuna koyabilirsiniz , ancak bu kaybolabilir ve / veya insanları karıştırabilir. Yani "yakalama" %~1
ve %~1
blok dışında en iyi görünüyor.IF NOT "%ARG:~0,2%" == "--"
.SHIFT
ne zaman kullanmak parametrelerden biri.SET FOO=%DEFAULT_FOO%
pişman olabilir, ancak alternatif blok IF "%FOO%" == "" SET FOO=%DEFAULT_FOO%
dışına eklemek olacaktır IF NOT "%ARG%" == ""
. Bu hala içeride Ancak, çünkü IF "%PARAM%" == "--foo"
blok %FOO%
değeri değerlendirilmiştir olurdu ve hiç blok girmeden önce bunu fark etmezler diye, set hem--foo
parametre mevcuttu ve aynı zamanda o %FOO%
değeri eksikti.ECHO Missing bar value. 1>&2
stderr'e hata iletisi gönderir.ECHO:
ya da varyasyonlardan birini.Yeni bir toplu iş dosyası oluşturun (örnek: openclass.bat) ve bu satırı dosyaya yazın:
java %~n1
Sonra, toplu iş dosyasını, diyelim ki, system32 klasörüne yerleştirin, Java sınıfı dosyanıza gidin, sağ tıklayın, Özellikler, Birlikte aç ..., ardından toplu iş dosyanızı bulun, seçin ve bu ...
Benim için çalışıyor.
Not: Java sınıfını kapattığımda cmd penceresini kapatmanın bir yolunu bulamıyorum. Şimdilik...
start /wait java %~n1
Basit bir çözüm (soru eski olmasına rağmen)
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
çıktı
YourLocalPath>call "C:\Temp\test.bat" pass123
YourLocalPath>echo off
"Batch started"
"arg1 is pass123"
YourLocalPath>pause
Press any key to continue . . .
Burada YourLocalPath geçerli dizin yoludur.
İşleri basit tutmak için komut parametresini değişkente saklayın ve karşılaştırma için değişkeni kullanın.
Bu sadece yazmak için basit değil, aynı zamanda bakımı da kolaydır, bu nedenle daha sonra başka bir kişi veya uzun bir süre sonra komut dosyanızı okursanız, anlaşılması ve bakımı kolay olacaktır.
Satır içi kod yazmak için: diğer cevaplara bakınız.
Döngüyü kullanmak için tüm argümanları ve saf toplu olarak alın:
Obs: Olmadan kullanmak için:?*&<>
@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
Kodunuz ihtiyaç duyduğu argüman numarasıyla bir şeyler yapmaya hazır, örneğin ...
@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
?*&<>