Dapatkah saya memiliki blok IF dalam file batch DOS?


97

Dalam file batch DOS kita hanya dapat memiliki 1 baris if badan pernyataan? Saya rasa saya menemukan tempat yang dapat saya gunakan ()untuk blok if seperti yang {}digunakan dalam bahasa pemrograman mirip C, tetapi tidak mengeksekusi pernyataan ketika saya mencoba ini. Tidak ada pesan kesalahan juga. Ini kode saya:

if %GPMANAGER_FOUND%==true(echo GP Manager is up
goto Continue7
)
echo GP Manager is down
:Continue7

Anehnya, baik "GP Manager up" maupun "GP Manager is down" tidak dicetak saat saya menjalankan file batch.



Ya, itu membantu. DOS menyebalkan. Jika saya ingin menggunakan beberapa pernyataan dalam jika atau saya harus menggunakan && di antara pernyataan? atau ada cara yang lebih elegan?
Hugh Darling

Jawaban:


141

Anda memang bisa membuat blok pernyataan untuk dieksekusi setelah kondisional. Tapi Anda memiliki sintaks yang salah. Tanda kurung harus digunakan persis seperti yang ditunjukkan:

if <statement> (
    do something
) else (
    do something else
)

Namun, saya tidak percaya bahwa ada sintaks bawaan untuk else-ifpernyataan. Sayangnya, Anda perlu membuat blok ifpernyataan bertingkat untuk menanganinya.


Kedua, %GPMANAGER_FOUND% == truetes itu tampak sangat mencurigakan bagi saya. Saya tidak tahu apa variabel lingkungan diatur atau bagaimana Anda mengaturnya, tetapi saya sangat meragukan bahwa kode yang Anda tunjukkan akan menghasilkan hasil yang Anda cari.


Kode contoh berikut berfungsi dengan baik untuk saya:

@echo off

if ERRORLEVEL == 0 (
    echo GP Manager is up
    goto Continue7
)
echo GP Manager is down
:Continue7

Harap perhatikan beberapa detail spesifik tentang kode sampel saya:

  • Spasi ditambahkan di antara akhir pernyataan bersyarat, dan tanda kurung buka.
  • Saya mengatur @echo offagar tidak melihat semua pernyataan yang dicetak ke konsol saat mereka mengeksekusi, dan sebagai gantinya hanya melihat output dari yang secara khusus dimulai echo.
  • Saya menggunakan ERRORLEVELvariabel built-in hanya sebagai pengujian. Baca lebih lanjut di sini

1
Lebih baik gunakan jika% ERRORLEVEL% == 0, karena varian lainnya selalu benar, karena JIKA ERRORLEVEL <N> benar, jika tingkat kesalahan sama atau lebih besar <N>, "==" diabaikan dalam kasus ini
jeb

@jeb: Saya pikir Anda mungkin telah melewatkan intinya. Menggunakan ERRORLEVELbukanlah jawaban untuk masalahnya. Saya hanya memposting contoh sintaks yang tepat. Bentuk mana pun dapat diterima dalam kasus ini, seperti yang akan dilakukan if 0 == 0atau ekspresi sepele lainnya. Namun memang, pastikan Anda memahami perbedaan antara variabel lingkungan %ERRORLEVEL%dan internal ERRORLEVELprosesor perintah. Raymond Chen menjelaskannya dengan baik di sini di blog ini .
Cody Grey

Bisakah Anda memiliki JIKA LAINNYA?
xagyg

1
Menambah komentar @mithofechelon, bahkan tanda kurung penutup yang tampaknya tidak berbahaya dalam pernyataan REM akan mengakhiri pemblokiran. misalnya Melempar REM This is a comment (or so I thought)ke dalam IFblok akan mengacaukan Anda.
rkagerer

2
Baik @mythofechelon dan @rkagerer menunjukkan masalah spesifik dari aturan umum yang perlu dikutip string. Anda tidak boleh mengkodekannya IF %somevar%==example_string2 harus selalu menjadi kode sehingga operan menyelesaikan menjadi IF "value_of_somevar"=="example_string2"untuk menghindari karakter khusus di salah satu operan string yang menyebabkan kesalahan sintaks dalam IFpernyataan. Nilai yang Anda setel harus selalu dilakukan karena set "somevar=value_of_somevar" sintaks itu memungkinkan Anda untuk keluar dari karakter khusus dalam nilai variabel, Catatan bahwa saya tidak bermaksud set somevar="value_of_somevar"
Lewati R

15

Logikanya, jawaban Cody seharusnya berhasil. Namun saya tidak berpikir command prompt menangani blok kode secara logis. Untuk kehidupan saya, saya tidak bisa membuatnya berfungsi dengan baik dengan lebih dari satu perintah di dalam blok. Dalam kasus saya, pengujian ekstensif mengungkapkan bahwa semua perintah di dalam blok sedang di-cache, dan dijalankan secara bersamaan di akhir blok. Ini tentu saja tidak memberikan hasil yang diharapkan. Berikut adalah contoh yang terlalu disederhanakan:

if %ERRORLEVEL%==0 (
set var1=blue
set var2=cheese
set var3=%var1%_%var2%
)

Ini harus memberikan var3 dengan nilai berikut:

blue_cheese

tetapi malah menghasilkan:

_

karena semua 3 perintah di-cache dan dijalankan secara bersamaan setelah keluar dari blok kode.

Saya dapat mengatasi masalah ini dengan menulis ulang blok if untuk hanya menjalankan satu perintah - goto - dan menambahkan beberapa label. Ini kikuk, dan saya tidak begitu menyukainya, tapi setidaknya berhasil.

if %ERRORLEVEL%==0 goto :error0
goto :endif

:error0
set var1=blue
set var2=cheese
set var3=%var1%_%var2%

:endif

8
Menggunakan ekspansi tertunda seharusnya berhasil: gunakan:set var3=!var1!_!var2!
Dracorat

4

Daripada goto mess, coba gunakan ampersand & atau double ampersand && (conditional to errorlevel 0) sebagai pemisah perintah.

Saya memperbaiki cuplikan skrip dengan trik ini, untuk meringkas, saya memiliki tiga file batch, satu yang memanggil dua lainnya setelah menemukan huruf mana yang telah ditetapkan oleh drive cadangan eksternal. Saya meninggalkan file pertama di drive eksternal utama sehingga panggilan ke rutin pencadangannya berfungsi dengan baik, tetapi panggilan ke yang kedua memerlukan perubahan drive aktif. Kode di bawah ini menunjukkan bagaimana saya memperbaikinya:

for %%b in (d e f g h i j k l m n o p q r s t u v w x y z) DO (
if exist "%%b:\Backup.cmd" %%b: & CALL "%%b:\Backup.cmd"
)

Mengapa ini tidak disukai? Inilah yang saya butuhkan.
ggb667

1
@ GCB667 - Untuk memperjelas @Louis "menulis" jawaban "yang tidak terkait dengan masalah mengapa pernyataan IF tidak berfungsi untuk poster asli. Ini terkait dengan jawaban oleh" vinniejohnson "(yang juga melewatkan masalah poster asli) .
Lewati R

1

Saya menemukan artikel ini dalam hasil yang dikembalikan oleh pencarian yang terkait dengan perintah IF dalam file batch, dan saya tidak dapat menahan kesempatan untuk memperbaiki kesalahpahaman bahwa blok IF terbatas pada perintah tunggal. Berikut ini adalah sebagian dari skrip perintah Windows NT produksi yang berjalan setiap hari pada mesin tempat saya menulis balasan ini.

    if "%COPYTOOL%" equ "R" (
    WWLOGGER.exe "%APPDATA%\WizardWrx\%~n0.LOG" "Using RoboCopy to make a backup of %USERPROFILE%\My Documents\Outlook Files\*"
    %TOOLPATH% %SRCEPATH% %DESTPATH% /copyall %RCLOGSTR% /m /np /r:0 /tee
    C:\BIN\ExitCodeMapper.exe C:\BIN\ExitCodeMapper.INI[Robocopy] %TEMP%\%~n0.TMP %ERRORLEVEL%
) else (
    WWLOGGER.exe "%APPDATA%\WizardWrx\%~n0.LOG" "Using XCopy to make a backup of %USERPROFILE%\My Documents\Outlook Files\*"
    call %TOOLPATH%  "%USERPROFILE%\My Documents\Outlook Files\*" "%USERPROFILE%\My Documents\Outlook Files\_backups" /f /m /v /y
    C:\BIN\ExitCodeMapper.exe C:\BIN\ExitCodeMapper.INI[Xcopy] %TEMP%\%~n0.TMP %ERRORLEVEL%
)

Mungkin blok dua atau lebih baris berlaku secara eksklusif untuk skrip perintah Windows NT (file .CMD), karena pencarian direktori skrip produksi dari aplikasi yang dibatasi untuk file batch sekolah lama (.BAT), mengungkapkan hanya blok satu perintah . Karena aplikasi telah menjalani perawatan yang diperpanjang (artinya saya tidak terlibat aktif dalam mendukungnya), saya tidak dapat mengatakan apakah itu karena saya tidak memerlukan lebih dari satu baris, atau saya tidak dapat membuatnya berfungsi.

Terlepas dari itu, jika yang terakhir benar, ada solusi sederhana; pindahkan beberapa baris ke file batch terpisah atau subrutin file batch. Saya tahu bahwa yang terakhir berfungsi di kedua jenis skrip.


0

Mungkin agak terlambat, tapi semoga bisa:

@echo off 

if %ERRORLEVEL% == 0 (
msg * 1st line WORKS FINE rem You can relpace msg * with any othe operation...
goto Continue1
)
:Continue1
If exist "C:\Python31" (
msg * 2nd line WORKS FINE rem You can relpace msg * with any othe operation...
    goto Continue2
)
:Continue2
If exist "C:\Python31\Lib\site-packages\PyQt4" (  
msg * 3th line WORKS FINE rem You can relpace msg * with any othe operation...
    goto Continue3
)
:Continue3
msg * 4th line WORKS FINE rem You can relpace msg * with any othe operation...
    goto Continue4
)
:Continue4
msg * "Tutto a posto" rem You can relpace msg * with any othe operation...
pause
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.