Saya perlu memberikan ID dan kata sandi ke file batch pada saat menjalankan daripada melakukan hardcoding pada file tersebut.
Seperti inilah baris perintah:
test.cmd admin P@55w0rd > test-log.txt
Saya perlu memberikan ID dan kata sandi ke file batch pada saat menjalankan daripada melakukan hardcoding pada file tersebut.
Seperti inilah baris perintah:
test.cmd admin P@55w0rd > test-log.txt
Jawaban:
Tip lain yang bermanfaat adalah menggunakan %*
berarti "semua". Sebagai contoh:
echo off
set arg1=%1
set arg2=%2
shift
shift
fake-command /u %arg1% /p %arg2% %*
Ketika Anda menjalankan:
test-command admin password foo bar
file batch di atas akan berjalan:
fake-command /u admin /p password admin password foo bar
Saya mungkin memiliki sintaks yang sedikit salah, tetapi ini adalah ide umum.
shift
"muncul" argumen dari daftar. Asumsi oleh OP adalah bahwa %*
hanya akan menghasilkan argumen yang tersisa, tetapi tidak berfungsi seperti itu, seperti kata @ Joey.
fake-command /u admin /p password admin password foo bar
. Ini ditunjukkan oleh @ Joey bertahun-tahun yang lalu.
Begini cara saya melakukannya:
@fake-command /u %1 /p %2
Begini tampilannya:
test.cmd admin P@55w0rd > test-log.txt
Yang %1
berlaku untuk parameter pertama yang %2
(dan inilah bagian yang sulit) berlaku untuk yang kedua. Anda dapat memiliki hingga 9 parameter yang dilewati dengan cara ini.
echo %1 %2
dan terlempar oleh kasing sederhana yang tidak dapat dilekatkan dengan @
dan fake-command
dengan params, berpikir kami akan mendapatkan fake-command.bat
konten nanti (dalam hal ini, terlalu rumit fake-command.bat
mungkin harus echo %2 %4
mengabaikan nama-nama param). Salah, doofus. TL; DR: Jangan sebodoh saya. 1. echo echo %1 %2 > test.bat
2 test word1 word2
.. 3. Keuntungan.
Jika Anda ingin secara cerdas menangani parameter yang hilang, Anda dapat melakukan sesuatu seperti:
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
Mengakses parameter kumpulan bisa sederhana dengan% 1,% 2, ...% 9 atau juga% *,
tetapi hanya jika kontennya sederhana.
Tidak ada cara sederhana untuk konten yang kompleks seperti "&"^&
, karena tidak mungkin mengakses% 1 tanpa menghasilkan kesalahan.
set var=%1
set "var=%1"
set var=%~1
set "var=%~1"
Garis melebar ke
set var="&"&
set "var="&"&"
set var="&"&
set "var="&"&"
Dan setiap baris gagal, karena salah satu di &
luar tanda kutip.
Ini dapat diatasi dengan membaca dari file sementara versi parameter yang dikomentari .
@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!'
Caranya adalah dengan mengaktifkan echo on
dan memperluas% 1 setelah rem
pernyataan (berfungsi juga dengan %2 .. %*
).
Jadi, bahkan "&"&
dapat digaungkan tanpa menghasilkan kesalahan, seperti yang dikatakan.
Tetapi untuk dapat mengarahkan kembali output echo on
, Anda memerlukan dua for-loop.
Karakter tambahan * #
digunakan untuk aman terhadap konten seperti /?
(akan menunjukkan bantuan untuk REM
).
Atau tanda sisipan ^ pada baris akhir bisa berfungsi sebagai karakter multiline, bahkan setelah a rem
.
Kemudian membaca output parameter rem dari file, tetapi hati-hati.
FOR / F harus bekerja dengan ekspansi yang tertunda, selain konten dengan "!" akan dihancurkan.
Setelah menghapus karakter tambahan param1
, Anda mendapatkannya.
Dan untuk digunakan param1
dengan cara yang aman, memungkinkan ekspansi tertunda.
&
, solusi Anda hanya berfungsi dengan konten sederhana
test.bat ^&
dan gagal. Hanya test.bat "&"
berhasil, tapi itu bukan maksud saya. Anda tidak dapat menggunakan %*
, %1
dengan cara yang aman tanpa teknik REM
&
dan juga kutipan"
Yap, dan jangan lupa untuk menggunakan variabel seperti %%1
saat menggunakan if
dan for
dan geng.
Jika Anda lupa dobel %
, maka Anda akan mengganti argumen baris perintah (mungkin nol) dan Anda akan menerima beberapa pesan kesalahan yang cukup membingungkan.
if
dan for
?
for %%d in (*) do echo %%d
dari baris perintah:for %d in (*) do echo %d
@for %%2 in (testing) do @echo %%2 %1
dalam file batch, menghasilkan testing 1
ketika dipanggil dengan 1 ( test 1
).
%%1
tidak mengakses argumen baris perintah, dan itu juga salah untuk IF
perintah. Hanya FOR
perintah (dalam file batch) membutuhkan persen ganda, tetapi bahkan kemudian %%1
akan menentukan UNTUK parameter dan tidak argumen akses
Tidak perlu menyulitkannya. Ini hanya perintah% 1% 2 parameter, misalnya,
@echo off
xcopy %1 %2 /D /E /C /Q /H /R /K /Y /Z
echo copied %1 to %2
pause
"Jeda" menampilkan apa yang telah dilakukan file batch dan menunggu Anda menekan tombol APA SAJA. Simpan itu sebagai xx.bat di folder Windows.
Untuk menggunakannya, ketik, misalnya:
xx c:\f\30\*.* f:\sites\30
File batch ini menangani semua parameter yang diperlukan, seperti menyalin file saja, yang lebih baru, dll. Saya telah menggunakannya sejak sebelum Windows. Jika Anda suka melihat nama-nama file, karena mereka sedang disalin, biarkan Q
parameter.
Seorang teman bertanya kepada saya tentang subjek ini baru-baru ini, jadi saya pikir saya akan memposting bagaimana saya menangani argumen baris perintah dalam file batch.
Teknik ini memiliki sedikit overhead seperti yang akan Anda lihat, tetapi itu membuat file batch saya sangat mudah dimengerti dan cepat diimplementasikan. Serta mendukung struktur berikut:
>template.bat [-f] [--flag] [/f] [--namedvalue value] arg1 [arg2][arg3][...]
Jist itu adalah memiliki :init
, :parse
, dan :main
fungsi.
Contoh penggunaan
>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
Catatan: JIKA "%1"==""
akan menyebabkan masalah jika %1
dilampirkan dalam tanda kutip itu sendiri.
Dalam hal ini, gunakan IF [%1]==[]
atau, dalam NT 4 (SP6) dan hanya nanti, IF "%~1"==""
sebagai gantinya.
Mari kita tetap sederhana ini.
Ini file .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%
Berikut adalah 3 panggilan dari baris perintah.
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
)
Ini loop atas parameter batch (% *) baik yang dikutip atau tidak, kemudian gema setiap parameter.
test.bat *.txt
, test.bat cat^&dog
atauTest.bat /?
Saya menulis skrip read_params sederhana yang dapat disebut sebagai fungsi (atau eksternal .bat
) dan akan meletakkan semua variabel ke lingkungan saat ini. Itu tidak akan mengubah parameter asli karena fungsi sedang call
diedit dengan salinan parameter asli.
Misalnya, diberikan perintah berikut:
myscript.bat some -random=43 extra -greeting="hello world" fluff
myscript.bat
akan dapat menggunakan variabel setelah memanggil fungsi:
call :read_params %*
echo %random%
echo %greeting%
Inilah fungsinya:
: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
Keterbatasan
-force
. Anda bisa menggunakan -force=true
tetapi saya tidak bisa memikirkan cara untuk mengizinkan nilai kosong tanpa mengetahui daftar parameter sebelumnya yang tidak akan memiliki nilai.Changelog
-
parameter sebelumnya.Dalam file batch
set argument1=%1
set argument2=%2
echo %argument1%
echo %argument2%
% 1 dan% 2 masing-masing mengembalikan nilai argumen pertama dan kedua.
Dan di baris perintah, lewati argumen
Directory> batchFileName admin P@55w0rd
Output akan menjadi
admin
P@55w0rd
Terinspirasi oleh jawaban di tempat lain oleh @ Jon, saya telah membuat algoritma yang lebih umum untuk mengekstraksi parameter bernama, nilai opsional, dan switch.
Mari kita katakan bahwa kita ingin mengimplementasikan suatu utilitas foobar
. Itu membutuhkan perintah awal. Ini memiliki parameter opsional --foo
yang mengambil nilai opsional (yang tidak bisa menjadi parameter lain, tentu saja); jika nilai tidak ada, defaultnya adalah default
. Ini juga memiliki parameter opsional --bar
yang mengambil nilai yang diperlukan . Terakhir dapat mengambil bendera --baz
tanpa nilai yang diizinkan. Oh, dan parameter ini bisa datang dalam urutan apa pun.
Dengan kata lain, tampilannya seperti ini:
foobar <command> [--foo [<fooval>]] [--bar <barval>] [--baz]
Ini solusinya:
@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
agar variabel tidak keluar ke lingkungan panggilan.SET FOO=
, dll. Seandainya seseorang mendefinisikannya dalam lingkungan panggilan.%~1
untuk menghapus kutipan.IF "%ARG%" == ""
dan bukan IF [%ARG%] == []
karena [
dan ]
tidak bermain sama sekali dengan nilai yang berakhir dengan spasi.SHIFT
berada di dalam IF
blok, argumen saat ini seperti %~1
tidak mendapatkan pembaruan karena mereka ditentukan ketika IF
diuraikan. Anda dapat menggunakan %~1
dan %~2
di dalam IF
blok, tetapi itu akan membingungkan karena Anda punya SHIFT
. Anda bisa meletakkannya SHIFT
di ujung blok untuk kejelasan, tetapi itu mungkin akan hilang dan / atau membingungkan orang juga. Jadi "menangkap" %~1
dan di %~1
luar blok sepertinya yang terbaik.IF NOT "%ARG:~0,2%" == "--"
.SHIFT
ketika Anda menggunakan salah satu parameter.SET FOO=%DEFAULT_FOO%
disesalkan, tetapi alternatifnya adalah menambahkan blok IF "%FOO%" == "" SET FOO=%DEFAULT_FOO%
di luar IF NOT "%ARG%" == ""
. Namun karena ini masih dalam IF "%PARAM%" == "--foo"
blok, yang %FOO%
nilai akan telah dievaluasi dan ditetapkan sebelum Anda pernah masuk blok, sehingga Anda tidak akan mendeteksi bahwa kedua yang --foo
parameter hadir dan juga bahwa %FOO%
nilai yang hilang.ECHO Missing bar value. 1>&2
mengirim pesan kesalahan ke stderr.ECHO:
atau salah satu variasi.Buat file batch baru (contoh: openclass.bat) dan tulis baris ini di file:
java %~n1
Kemudian tempatkan file batch, katakanlah, folder system32, buka file kelas Java Anda, klik kanan, Properties, Open with ..., lalu cari file batch Anda, pilih dan itu ...
Ini bekerja untuk saya.
PS: Saya tidak bisa menemukan cara untuk menutup jendela cmd ketika saya menutup kelas Java. Untuk sekarang...
start /wait java %~n1
Solusi sederhana (meskipun pertanyaan sudah lama)
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
keluaran
YourLocalPath>call "C:\Temp\test.bat" pass123
YourLocalPath>echo off
"Batch started"
"arg1 is pass123"
YourLocalPath>pause
Press any key to continue . . .
Di mana YourLocalPath adalah jalur direktori saat ini.
Untuk menjaga hal-hal sederhana, simpan param perintah dalam variabel dan gunakan variabel untuk perbandingan.
Ini tidak hanya sederhana untuk ditulis tetapi juga mudah untuk dipertahankan sehingga jika nanti orang lain atau Anda membaca skrip Anda setelah jangka waktu yang lama, itu akan mudah dipahami dan dikelola.
Untuk menulis kode sebaris: lihat jawaban lain.
Untuk menggunakan perulangan dapatkan semua argumen dan dalam batch murni:
Obs: Untuk menggunakan tanpa:?*&<>
@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
Kode Anda siap untuk melakukan sesuatu dengan nomor argumen yang diperlukan, seperti ...
@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
?*&<>