Bagaimana cara memeriksa parameter baris perintah di file ".bat"?


103

OS saya adalah Windows Vista. Saya perlu memiliki file ".bat" di mana saya perlu memeriksa apakah pengguna memasukkan parameter baris perintah atau tidak. Jika tidak, maka jika parameternya sama dengan -bmaka saya akan melakukan sesuatu jika tidak, saya akan menandai "Input tidak valid". Jika pengguna tidak memasukkan parameter baris perintah apa pun maka saya akan melakukan sesuatu. Saya telah membuat file .bat berikut. Ini berfungsi untuk -bdan tidak sama dengan -bkasus - tetapi gagal ketika pengguna tidak memberikan parameter baris perintah apa pun.

Saya selalu mendapatkan kesalahan:

GOTO was unexpected at this time.

Adakah yang bisa memberi tahu saya apa yang saya lakukan salah di sini?


ECHO OFF
CLS
ECHO.

IF [%1]==[/?] GOTO BLANK

IF %1=="-b" GOTO SPECIFIC

IF NOT %1=="-b" GOTO UNKNOWN

:SPECIFIC

ECHO SPECIFIC

GOTO DONE

:BLANK

ECHO No Parameter

GOTO DONE

:UNKNOWN

ECHO Unknown Option

GOTO DONE

:DONE

ECHO Done!

Jika Anda menambahkan tanda kurung (seperti di GOTO BLANKbaris) ke dua IFpernyataan lainnya, apakah itu memperbaiki masalah?
Jeremiah Willcock

Jawaban:


141

Anda perlu memeriksa apakah parameternya kosong: if "%~1"=="" goto blank

Setelah Anda selesai melakukannya, lakukan jika / else aktifkan -b: if "%~1"=="-b" (goto specific) else goto unknown

Mengitari parameter dengan tanda kutip mempermudah pemeriksaan hal-hal seperti parameter kosong / kosong / hilang. "~" memastikan tanda kutip ganda dihapus jika ada di argumen baris perintah.


Ini bekerja!! Hanya "lain" yang tidak diterima. Saya mendapatkan kesalahan: 'else' tidak dikenali sebagai perintah internal atau eksternal, program yang dapat dioperasikan atau file batch. Jadi saya menambahkan IF lain untuk kasus "tidak sama dengan -b". Terima kasih atas jawaban cepatnya.
javauser71

7
ELSE harus berada di baris yang sama dengan IF, atau harus tepat setelah braket
jeb

4
Ini tampaknya tidak berhasil untuk saya jika% 1 berisi spasi, yang mungkin terjadi jika ini adalah jalur lengkap ke file yang dapat dieksekusi. Lihat jawaban Jeremiah Willcock untuk solusi yang bekerja bahkan untuk parameter dengan spasi dalam nilainya.
Mark A. Fitzgerald

tidak akan diterima jika argumen Anda adalah a File, dalam hal ini Anda harus memeriksa saja existatau not exist. Inilah mengapa argumen Anda harus didefinisikan dengan baik, atau cukup gunakan PowerShell atau vbScript (jika Anda berusia 80-an ..)

1
Ini gagal untuk run.bat "a b". "%1"==""crash jika arg memiliki spasi. Lihat stackoverflow.com/a/46942471
wisbucky

27

Lihat http://ss64.com/nt/if.html untuk mendapatkan jawaban; perintahnya IF [%1]==[] GOTO NO_ARGUMENTatau serupa.


1
Tidak hanya ini JUGA bekerja! Ini hanya berfungsi, berbeda dengan "%1"=="". Saya harus menjelaskannya dalam jawaban saya sendiri.
Tomasz Gandor

1
ini akan rusak ketika% 1 dikutip, misalnya foo.bat "1st parameter" 2nd_param. Lihat stackoverflow.com/questions/2541767/…
matt wilkie

Penggunaan [%1]==[-b]tidak akan cocok jika arg dikutip. Contoh run.bat "-b". Lihat stackoverflow.com/a/46942471
wisbucky

20

Jawaban singkatnya - gunakan tanda kurung siku:

if [%1]==[] goto :blank

atau (ketika Anda perlu menangani argumen yang dikutip, lihat Edit di bawah):

if [%~1]==[] goto :blank

Mengapa? Anda mungkin bertanya. Nah, seperti yang dikatakan Jeremiah Willcock: http://ss64.com/nt/if.html - mereka menggunakannya! Oke, tapi apa yang salah dengan kutipannya?

Sekali lagi, jawaban singkatnya: kutipan itu "ajaib" - terkadang tanda kutip ganda (ganda) diubah menjadi tanda kutip tunggal (ganda). Dan mereka harus cocok, sebagai permulaan.

Pertimbangkan skrip kecil ini:

@rem argq.bat
@echo off

:loop 
if "%1"=="" goto :done
echo %1
shift
goto :loop

:done
echo Done.

Mari kita uji:

C:\> argq bla bla
bla
bla
Done.

Sepertinya berhasil. Tapi sekarang, mari beralih ke gigi kedua:

C:\> argq "bla bla"
bla""=="" was unexpected at this time.

Boom Ini tidak bernilai benar, juga tidak bernilai salah. Script MATI. Jika Anda seharusnya mematikan reaktor di suatu tempat, ya - sial. Anda sekarang akan mati seperti Harry Daghlian.

Anda mungkin berpikir - Oke, argumen tidak boleh berisi tanda kutip. Jika mereka melakukannya, ini terjadi. Salah Ini beberapa penghiburan:

C:\> argq ""bla bla""
""bla
bla""
Done.

Oh ya. Jangan khawatir - terkadang ini akan berhasil.

Mari coba skrip lain:

@rem args.bat
@echo off

:loop 
if [%1]==[] goto :done
echo %1
shift
goto :loop

:done
echo Done.

Anda dapat menguji sendiri, apakah itu berfungsi dengan baik untuk kasus di atas. Ini logis - tanda kutip tidak ada hubungannya dengan tanda kurung, jadi tidak ada keajaiban di sini. Tapi bagaimana dengan membumbui args dengan tanda kurung?

D:\>args ]bla bla[
]bla
bla[
Done.

D:\>args [bla bla]
[bla
bla]
Done.

Tidak beruntung disana. Tanda kurung tidak bisa mencekik cmd.exeparser.

Mari kita kembali ke kutipan jahat sejenak. Masalahnya ada di sana, ketika argumen diakhiri dengan kutipan:

D:\>argq "bla1 bla2"
bla2""=="" was unexpected at this time.

Bagaimana jika saya lulus hanya:

D:\>argq bla2"
The syntax of the command is incorrect.

Skrip tidak akan berjalan sama sekali. Sama untuk args.bat:

D:\>args bla2"
The syntax of the command is incorrect.

Tapi apa yang saya dapatkan, ketika jumlah "-karakter "cocok" (yaitu - genap), dalam kasus seperti itu:

D:\>args bla2" "bla3
bla2" "bla3
Done.

BAGUS - Saya harap Anda mempelajari sesuatu tentang bagaimana .batfile membagi argumen baris perintah mereka (PETUNJUK: * Ini tidak persis seperti di bash). Argumen di atas mengandung spasi. Tetapi tanda kutip tidak dihapus secara otomatis.

Dan argq? Bagaimana reaksinya terhadap itu? Dapat diprediksi:

D:\>argq bla2" "bla3
"bla3"=="" was unexpected at this time.

Jadi - pikirkan sebelum Anda mengatakan: "Tahu apa? Gunakan saja tanda kutip. [Karena, bagi saya, ini terlihat lebih bagus]".

Edit

Baru-baru ini, ada komentar tentang jawaban ini - yah, tanda kurung siku "tidak dapat menangani" melewati argumen yang dikutip dan memperlakukannya seolah-olah tidak dikutip.

Sintaksnya:

if "%~1"=="" (...)

Bukan beberapa keunggulan yang baru ditemukan dari tanda kutip ganda, tetapi tampilan fitur rapi dari tanda kutip dari variabel argumen, jika karakter pertama dan terakhir adalah tanda kutip ganda.

"Teknologi" ini bekerja dengan baik dengan tanda kurung siku:

if [%~1]==[] (...)

Ini adalah hal yang berguna untuk menunjukkan hal ini, jadi saya juga mendukung jawaban baru tersebut.

Terakhir, penggemar kutipan ganda, apakah argumen formulir tersebut ""ada di buku Anda, atau kosong? Hanya askin ';)


1
Tanda kurung siku [%1]==[-b]tidak akan cocok jika arg dikutip seperti ini run.bat "-b". Lihat stackoverflow.com/a/46942471
wisbucky

Secara historis dicatat: [%1]==[-b]dan "%1"=="-b"sama untuk win 98 dan skrip batch sistem MS / PC-DOS sebelumnya. Sejak win 2000 / NT memperkenalkan sintaks di if "%~1"=="-b"mana tanda kutip ganda memiliki arti khusus yang merupakan cara Anda harus membuat kode skrip karena memberikan perlindungan yang lebih kuat. Tanda kutip ganda menghilangkan arti karakter khusus (coba & | dan% karakter di baris perintah Anda). 99,9% contoh bekerja dengan sintaks tanda kutip ganda - contoh Anda argq bla2" "bla3hanya kasus untuk membenarkan tanda kurung siku. Tanda kutip ganda yang disematkan adalah resep untuk bencana - katakan saja
Lewati R

@SkipR - itulah sebabnya di sistem file Windows, Anda tidak dapat memiliki karakter khusus ini dalam nama. Saya tidak memiliki bukti matematis, tetapi saya pikir TIDAK semuanya dapat dikutip (dalam arti - dibuat kata demi kata melalui beberapa urutan pelarian, dll.) Di cmdshell. Di sistem lain Anda terkadang dapat mengutip semuanya, termasuk karakter NUL. ( stackoverflow.com/questions/2730732/… ) - pertanyaan ini hanya menunjukkan, Anda perlu menggunakan beberapa program eksternal.
Tomasz Gandor

8

Selain jawaban lain, yang saya langgan, Anda dapat mempertimbangkan untuk menggunakan /Isakelar IFperintah.

... tombol / I, jika ditentukan, mengatakan untuk melakukan perbandingan string tidak sensitif huruf besar / kecil.

mungkin bisa membantu jika Anda ingin memberikan fleksibilitas tidak peka huruf besar / kecil kepada pengguna Anda untuk menentukan parameter.

IF /I "%1"=="-b" GOTO SPECIFIC

5

Anda membandingkan string. Jika argumen dihilangkan, %1diperluas menjadi kosong sehingga perintah menjadi IF =="-b" GOTO SPECIFICmisalnya (yang merupakan kesalahan sintaks). Bungkus string Anda dengan tanda kutip (atau tanda kurung siku).

REM this is ok
IF [%1]==[/?] GOTO BLANK

REM I'd recommend using quotes exclusively
IF "%1"=="-b" GOTO SPECIFIC

IF NOT "%1"=="-b" GOTO UNKNOWN

IF [% 1] == [/?] Tidak berfungsi tetapi saya melakukannya IF [% 1] == [] atau "% 1" == "", maka berhasil. Pokoknya sekarang saya bisa pergi. Terima kasih atas tanggapan cepat Anda.
javauser71

5

Sebenarnya, semua jawaban lainnya memiliki kekurangan. Cara paling andal adalah:

IF "%~1"=="-b" (GOTO SPECIFIC) ELSE (GOTO UNKNOWN)

Penjelasan detail:

Penggunaan "%1"=="-b"akan gagal total jika memberikan argumen dengan spasi dan tanda kutip. Ini adalah metode yang paling tidak dapat diandalkan.

IF "%1"=="-b" (GOTO SPECIFIC) ELSE (GOTO UNKNOWN)

C:\> run.bat "a b"

b""=="-b" was unexpected at this time.

Menggunakan [%1]==[-b]lebih baik karena tidak akan crash dengan spasi dan tanda kutip, tetapi tidak akan cocok jika argumen diapit oleh tanda kutip.

IF [%1]==[-b] (GOTO SPECIFIC) ELSE (GOTO UNKNOWN)

C:\> run.bat "-b"

(does not match, and jumps to UNKNOWN instead of SPECIFIC)

Menggunakan "%~1"=="-b"adalah yang paling andal. %~1akan menghapus kutipan di sekitarnya jika ada. Jadi ini bekerja dengan dan tanpa tanda kutip, dan juga tanpa argumen.

IF "%~1"=="-b" (GOTO SPECIFIC) ELSE (GOTO UNKNOWN)

C:\> run.bat
C:\> run.bat -b
C:\> run.bat "-b"
C:\> run.bat "a b"

(all of the above tests work correctly)

1
Ini bukan akhir dari tanda kurung siku, Anda lihat: IF [%~1]==[]- ini berfungsi, dan bahkan menangani "-b". Anda hanya perlu berpikir di dalam kotak, erm, persegi [tanda kurung].
Tomasz Gandor

3

Saya telah berjuang baru-baru ini dengan penerapan sakelar parameter kompleks dalam file batch jadi inilah hasil penelitian saya. Tidak ada jawaban yang diberikan sepenuhnya aman, contoh:

"%1"=="-?" tidak akan cocok jika parameter diapit tanda kutip (diperlukan untuk nama file, dll.) atau akan mogok jika parameter dalam tanda kutip dan memiliki spasi (sekali lagi sering terlihat dalam nama file)

@ECHO OFF
SETLOCAL
echo.
echo starting parameter test...
echo.
rem echo First parameter is %1
if "%1"=="-?" (echo Condition is true, param=%1) else (echo Condition is false, param=%1)
C:\>test.bat -?

starting parameter test...

Condition is true, param=-?

C:\>test.bat "-?"

starting parameter test...

Condition is false, param="-?"

Kombinasi apa pun dengan tanda kurung siku [%1]==[-?]atau [%~1]==[-?]akan gagal jika parameter memiliki spasi dalam tanda kutip:

@ECHO OFF
SETLOCAL 
echo.
echo starting parameter test...
echo.
echo First parameter is %1
if [%~1]==[-?] (echo Condition is true, param=%1) else (echo Condition is false, param=%1)

C:\>test.bat "long file name"

starting parameter test...

First parameter is "long file name"
file was unexpected at this time.

Solusi teraman yang diusulkan "%~1"=="-?"akan macet dengan parameter kompleks yang menyertakan teks di luar tanda kutip dan teks dengan spasi di dalam tanda kutip:

@ECHO OFF
SETLOCAL 
echo.
echo starting parameter test...
echo.
echo First parameter is %1
if "%~1"=="-?" (echo Condition is true, param=%1) else (echo Condition is false, param=%1)

C:\>test.bat -source:"long file name"

starting parameter test...

First parameter is -source:"long file name"
file was unexpected at this time.

Satu-satunya cara untuk memastikan semua skenario di atas tercakup adalah dengan menggunakan EnableDelayedExpansion dan meneruskan parameter dengan referensi (bukan berdasarkan nilai) menggunakan variabel. Kemudian bahkan skenario yang paling kompleks pun akan bekerja dengan baik:

@ECHO OFF
SETLOCAL EnableDelayedExpansion
echo.
echo starting parameter test...
echo.
echo First parameter is %1
:: we assign the parameter to a variable to pass by reference with delayed expansion
set "var1=%~1"
echo var1 is !var1!
:: we assign the value to compare with to a second variable to pass by reference with delayed expansion
set "var2=-source:"c:\app images"\image.png"
echo var2 is !var2!
if "!var1!"=="!var2!" (echo Condition is true, param=!var1!) else (echo Condition is false, param=!var1!)
C:\>test.bat -source:"c:\app images"\image.png

starting parameter test...

First parameter is -source:"c:\app images"\image.png
var1 is -source:"c:\app images"\image.png
var2 is -source:"c:\app images"\image.png
Condition is true, param=-source:"c:\app images"\image.png

C:\>test.bat -source:"c:\app images"\image1.png

starting parameter test...

First parameter is -source:"c:\app images"\image1.png
var1 is -source:"c:\app images"\image1.png
var2 is -source:"c:\app images"\image.png
Condition is false, param=-source:"c:\app images"\image1.png

C:\>test.bat -source:"c:\app images\image.png"

starting parameter test...

First parameter is -source:"c:\app images\image.png"
var1 is -source:"c:\app images\image.png"
var2 is -source:"c:\app images"\image.png
Condition is false, param=-source:"c:\app images\image.png"

0

Batch Windows memiliki kata kunci DEFINED untuk melakukan ini.

IF DEFINED %~1 foo
IF NOT DEFINED %~1 bar

Terima kasih David. Saya tidak tahu mengapa gagal ada kereta kembali dan jalur baru antara JIKA dan JIKA TIDAK. Saya bahkan tidak menyadarinya.
Charles
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.