DOS toplu iş dosyasında bir IF bloğuna sahip olabilir miyim?


98

Bir DOS toplu iş dosyasında sadece 1 satır if ifade gövdesi olabilir mi? Sanırım C benzeri programlama dillerinde kullanılan ()gibi bir if bloğu için kullanabileceğim bir yer buldum {}, ama bunu denediğimde ifadeleri çalıştırmıyor. Hata mesajı da yok. Bu benim kodum:

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

Tuhaf bir şekilde, toplu iş dosyasını çalıştırdığımda ne "GP Manager açık" ne de "GP Manager kapalı" yazdırılıyor.


Belki bu yardımcı olabilir: commandwindows.com/batchfiles-branching.htm
esaj

Ya, bu yardımcı olur. DOS berbat. İfadeler arasında && kullanmalıyım ya da yoksa birden fazla ifade kullanmak istersem? yoksa daha zarif bir yol var mı?
Hugh Darling

Yanıtlar:


143

Bir koşuldan sonra yürütülecek bir ifade bloğu oluşturabilirsiniz. Ama sözdizimi yanlış. Parantezler tam olarak gösterildiği gibi kullanılmalıdır:

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

Bununla birlikte, else-ififadeler için yerleşik bir sözdizimi olduğuna inanmıyorum . Ne yazık ki if, bunun üstesinden gelmek için iç içe geçmiş ifade blokları oluşturmanız gerekecek .


İkincisi, bu %GPMANAGER_FOUND% == truetest bana çok şüpheli görünüyor. Ortam değişkeninin neye ayarlandığını veya onu nasıl ayarladığını bilmiyorum, ancak gösterdiğiniz kodun aradığınız sonucu üreteceğinden çok şüpheliyim.


Aşağıdaki örnek kod benim için iyi çalışıyor:

@echo off

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

Lütfen örnek kodumla ilgili birkaç özel ayrıntıya dikkat edin:

  • Koşullu ifadenin sonu ile açılış parantezi arasına eklenen boşluk.
  • Konsola yazdırılan tüm ifadeleri yürütülürken görmekten kaçınmayı ve bunun yerine özellikle başlayanların çıktılarını @echo offgörmeyi ayarlıyorum .echo
  • Yerleşik ERRORLEVELdeğişkeni sadece bir test olarak kullanıyorum. Daha fazlasını buradan okuyun

1
% ERRORLEVEL% == 0 ise, diğer değişken her zaman doğruysa daha iyi kullanın, çünkü EĞER ERRORLEVEL <N> doğruysa, <N> hata düzeyi eşitse veya daha büyükse, bu durumda "==" yoksayılır
jeb

@jeb: Sanırım noktayı kaçırmışsınızdır. Kullanmak ERRORLEVEL, sorununun çözümü değil. Sadece uygun sözdizimi için bir örnek yayınlıyordum. Bu durumda her iki form da, tıpkı olması gerektiği gibi if 0 == 0veya diğer önemsiz ifadeler olarak kabul edilebilir . Ama aslında, ortam değişkeni %ERRORLEVEL%ile ERRORLEVELkomut işlemcisinin içi arasındaki farkı anladığınızdan emin olun . Raymond Chen bunu bu blogda güzelce açıklıyor .
Cody Grey

ELSE IF olabilir mi?
xagyg

1
@ Mythofechelon'un yorumuna ek olarak, bir REM ifadesindeki görünüşte zararsız bir kapatma parantezi bile bloğu sona erdirecektir. Örneğin bloğun REM This is a comment (or so I thought)içine atmak IFsizi mahveder.
rkagerer

2
Hem @mythofechelon hem de @rkagerer, dizelerin alıntılanması gereken genel bir kuralın belirli konularını işaret ediyor. Kodun asla IF %somevar%==example_string2 karşı işlenen çözmek yüzden hep kodu olmalıdır IF "value_of_somevar"=="example_string2"ya dize işlenen neden sözdizimi hataları özel karakterler önlemek için IFdeyimi. Ayarladığınız Değerler her zaman yapılmalı gibi set "somevar=value_of_somevar" bu sözdizimi, Not değişken değerlerinde özel karakterler kaçmasına izin verir Bunu kastetmiyorum set somevar="value_of_somevar"
atla

15

Mantıken, Cody'nin cevabı olmalıdır çalışır. Ancak komut isteminin bir kod bloğunu mantıksal olarak işlediğini düşünmüyorum. Hayatım boyunca, bloğun içindeki tek bir komuttan daha fazla düzgün çalışmasını sağlayamıyorum. Benim durumumda, kapsamlı testler, blok içindeki tüm komutların önbelleğe alındığını ve bloğun sonunda aynı anda yürütüldüğünü ortaya çıkardı. Bu elbette beklenen sonuçları vermez. İşte aşırı basitleştirilmiş bir örnek:

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

Bu , var3'e aşağıdaki değeri sağlamalıdır:

blue_cheese

ancak bunun yerine şunu verir:

_

çünkü 3 komutun tümü önbelleğe alınır ve kod bloğundan çıkıldığında aynı anda yürütülür.

Bu sorunun üstesinden, if bloğunu yalnızca bir komutu - goto - çalıştırmak için yeniden yazıp birkaç etiket ekleyerek aşabildim. Hantal ve pek sevmiyorum ama en azından işe yarıyor.

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

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

:endif

8
Gecikmeli genişletmeyi kullanmak işe set var3=!var1!_!var2!
yaramalı

4

Bu gitme karmaşası yerine, komut ayırıcıları olarak ampersan & veya çift ve && (0 hata düzeyine koşullu) kullanmayı deneyin.

Bu numara ile bir komut dosyası parçacığını düzelttim, özetlemek gerekirse, biri harici yedekleme sürücülerinin hangi harflerin atandığını bulduktan sonra diğer ikisini çağıran üç toplu iş dosyam var. İlk dosyayı birincil harici sürücüde bıraktım, böylece yedekleme rutinine yapılan aramalar iyi çalıştı, ancak ikinciye yapılan aramalar aktif bir sürücü değişikliği gerektirdi. Aşağıdaki kod, onu nasıl düzelttiğimi gösterir:

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"
)

Bu neden reddedildi? Bu tam olarak ihtiyacım olan şey.
ggb667

1
@ GCB667 - @Louis'i açıklığa kavuşturmak için ", IF ifadesinin orijinal poster için neden işe yaramadığıyla ilgili olmayan bir" yanıt "yazdı." Vinniejohnson "tarafından verilen bir yanıtla ilgili (bu da orijinal poster sorununu kaçırdı) .
Atla R

1

Bu makaleye bir toplu iş dosyasında IF komutuyla ilgili bir aramadan dönen sonuçlarda rastladım ve IF bloklarının tek komutlarla sınırlı olduğu şeklindeki yanlış kanıyı düzeltme fırsatına karşı koyamadım. Aşağıda, bu yanıtı oluşturduğum makinede günlük olarak çalışan bir üretim Windows NT komut betiğinin bir bölümü bulunmaktadır.

    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%
)

Belki de iki veya daha fazla satırlık bloklar yalnızca Windows NT komut betikleri (.CMD dosyaları) için geçerlidir, çünkü eski okul toplu iş (.BAT) dosyalarıyla sınırlı bir uygulamanın üretim komut dosyaları dizininde yapılan bir arama, yalnızca bir komutlu blokları ortaya çıkarmıştır. . Uygulama uzatılmış bakıma girdiğinden (yani onu desteklemeye aktif olarak katılmadığım için), bunun birden fazla hatta ihtiyacım olmadığından mı yoksa onları çalıştırmamamdan mı kaynaklandığını söyleyemiyorum.

Ne olursa olsun, ikincisi doğruysa, basit bir çözüm vardır; birden çok satırı ayrı bir toplu iş dosyasına veya bir toplu iş dosyası alt yordamına taşıyın. İkincisinin her iki tür senaryoda da çalıştığını biliyorum.


0

Belki biraz geç, ama umarım cehennemdir:

@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
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.