Tôi có thể có khối IF trong tệp loạt DOS không?


96

Trong một tệp loạt DOS, chúng ta chỉ có thể có 1 dòng lệnh if thân? Tôi nghĩ rằng tôi đã tìm thấy ở đâu đó mà tôi có thể sử dụng ()cho một khối if giống như {}được sử dụng trong các ngôn ngữ lập trình giống C, nhưng nó không thực thi các câu lệnh khi tôi thử điều này. Không có thông báo lỗi. Đây là mã của tôi:

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

Kỳ lạ là cả "Trình quản lý GP đang hoạt động" cũng như "Trình quản lý GP không hoạt động" không được in khi tôi chạy tệp hàng loạt.


Có lẽ sức mạnh này giúp đỡ: commandwindows.com/batchfiles-branching.htm
esaj

Ya, có ích. DOS thật tệ. Nếu tôi muốn sử dụng nhiều câu lệnh trong if hay tôi phải sử dụng && giữa các câu lệnh? hay có cách nào tao nhã hơn không?
Hugh Darling

Câu trả lời:


139

Bạn thực sự có thể đặt tạo một khối câu lệnh để thực thi sau một điều kiện. Nhưng bạn đã sai cú pháp. Dấu ngoặc đơn phải được sử dụng chính xác như được hiển thị:

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

Tuy nhiên, tôi không tin rằng có bất kỳ cú pháp tích hợp nào cho các else-ifcâu lệnh. Thật không may, bạn sẽ cần phải tạo các khối ifcâu lệnh lồng nhau để xử lý điều đó.


Thứ hai, %GPMANAGER_FOUND% == truebài kiểm tra đó có vẻ đáng ngờ đối với tôi. Tôi không biết biến môi trường được đặt thành gì hoặc cách bạn đặt nó, nhưng tôi rất nghi ngờ rằng đoạn mã bạn đã hiển thị sẽ tạo ra kết quả mà bạn đang tìm kiếm.


Mã mẫu sau hoạt động tốt đối với tôi:

@echo off

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

Vui lòng lưu ý một số chi tiết cụ thể về mã mẫu của tôi:

  • Khoảng trắng được thêm vào giữa phần cuối của câu lệnh điều kiện và dấu ngoặc đơn mở.
  • Tôi đang thiết lập @echo offđể không nhìn thấy tất cả các câu lệnh được in ra bảng điều khiển khi chúng thực thi và thay vào đó chỉ xem kết quả của những câu lệnh bắt đầu cụ thể echo.
  • Tôi đang sử dụng ERRORLEVELbiến tích hợp chỉ như một thử nghiệm. Đọc thêm tại đây

1
Sử dụng tốt hơn nếu% ERRORLEVEL% == 0, vì biến thể khác luôn đúng, vì IF ERRORLEVEL <N> là true, nếu errorlevel bằng hoặc lớn hơn <N>, "==" được bỏ qua trong trường hợp này
jeb

@jeb: Tôi nghĩ bạn có thể đã bỏ lỡ điểm. Sử dụng ERRORLEVELkhông phải là câu trả lời cho vấn đề của anh ta. Tôi chỉ đơn giản là đăng một ví dụ về cú pháp thích hợp. Trong trường hợp này, có thể chấp nhận một trong hai hình thức, giống như if 0 == 0hoặc bất kỳ biểu thức tầm thường nào khác. Nhưng thực sự, hãy đảm bảo rằng bạn hiểu sự khác biệt giữa biến môi trường %ERRORLEVEL%và biến bên trong ERRORLEVELcủa bộ xử lý lệnh. Raymond Chen giải thích nó một cách độc đáo trên blog này .
Cody Grey

Bạn có thể có IF ELSE không?
xagyg

1
Thêm vào bình luận của @ mythofechelon, ngay cả một dấu ngoặc đơn có vẻ vô hại trong câu lệnh REM cũng sẽ kết thúc khối. ví dụ: ném REM This is a comment (or so I thought)vào IFkhối sẽ làm bạn rối tung lên.
rkagerer

2
Cả @mythofechelon và @rkagerer đều chỉ ra các vấn đề cụ thể của quy tắc chung mà các chuỗi cần được trích dẫn. Bạn không bao giờ nên viết mã, IF %somevar%==example_string2 nó phải luôn là mã vì vậy toán hạng giải quyết thành IF "value_of_somevar"=="example_string2"để tránh các ký tự đặc biệt trong một trong hai toán hạng chuỗi gây ra lỗi cú pháp trong IFcâu lệnh. Các giá trị bạn đặt phải luôn được thực hiện vì set "somevar=value_of_somevar" cú pháp đó cho phép bạn thoát các ký tự đặc biệt trong các giá trị biến, Lưu ý ý tôi không phải vậy set somevar="value_of_somevar"
Bỏ qua R

15

Về mặt logic, câu trả lời của Cody sẽ hoạt động. Tuy nhiên, tôi không nghĩ rằng dấu nhắc lệnh xử lý một khối mã một cách hợp lý. Đối với cuộc sống của tôi, tôi không thể làm cho nó hoạt động bình thường với bất kỳ lệnh nào ngoài một lệnh duy nhất trong khối. Trong trường hợp của tôi, thử nghiệm mở rộng cho thấy rằng tất cả các lệnh trong khối đang được lưu vào bộ nhớ đệm và được thực thi đồng thời ở cuối khối. Điều này tất nhiên không mang lại kết quả như mong đợi. Đây là một ví dụ đơn giản hóa quá mức:

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

Điều này sẽ cung cấp cho var3 giá trị sau:

blue_cheese

nhưng thay vào đó mang lại:

_

bởi vì cả 3 lệnh đều được lưu vào bộ nhớ đệm và được thực thi đồng thời khi thoát khỏi khối mã.

Tôi đã có thể khắc phục sự cố này bằng cách viết lại khối if để chỉ thực thi một lệnh - goto - và thêm một vài nhãn. Nó cồng kềnh, và tôi không thích nó lắm, nhưng ít nhất nó hoạt động.

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

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

:endif

8
Sử dụng mở rộng chậm nên làm việc: sử dụng:set var3=!var1!_!var2!
Dracorat

4

Thay vì mớ hỗn độn goto này, hãy thử sử dụng dấu và & hoặc dấu kép và && (có điều kiện đến mức lỗi 0) làm dấu phân tách lệnh.

Tôi đã sửa một đoạn mã tập lệnh bằng thủ thuật này, tóm lại, tôi có ba tệp hàng loạt, một tệp gọi hai tệp kia sau khi tìm thấy các ký tự mà ổ đĩa sao lưu bên ngoài đã được gán. Tôi để tệp đầu tiên trên ổ đĩa ngoài chính để các lệnh gọi đến quy trình sao lưu của nó hoạt động tốt, nhưng các lệnh gọi đến tệp thứ hai yêu cầu thay đổi ổ đĩa đang hoạt động. Đoạn mã dưới đây cho thấy cách tôi đã sửa nó:

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

Tại sao điều này lại bị phản đối? Đây chính xác là những gì tôi cần.
ggb667

1
@ GCB667 - Để làm rõ @Louis "đã viết một" câu trả lời "không liên quan đến vấn đề tại sao câu lệnh IF không hoạt động đối với người đăng gốc. Nó liên quan đến câu trả lời của" vinniejohnson "(cũng bỏ sót vấn đề áp phích gốc) .
Bỏ qua R

1

Tôi đã xem qua bài viết này trong kết quả được trả về bởi một tìm kiếm liên quan đến lệnh IF trong một tệp hàng loạt và tôi không thể cưỡng lại cơ hội sửa chữa quan niệm sai lầm rằng khối IF bị giới hạn trong các lệnh đơn lẻ. Sau đây là một phần của tập lệnh Windows NT sản xuất chạy hàng ngày trên máy mà tôi đang soạn câu trả lời này.

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

Có lẽ các khối gồm hai hoặc nhiều dòng chỉ áp dụng cho các tập lệnh lệnh Windows NT (tệp .CMD), vì việc tìm kiếm thư mục tập lệnh sản xuất của một ứng dụng bị hạn chế đối với các tệp hàng loạt (.BAT) cũ, chỉ tiết lộ các khối lệnh một . Vì ứng dụng đã được bảo trì mở rộng (có nghĩa là tôi không tích cực tham gia hỗ trợ nó), tôi không thể nói liệu đó là vì tôi không cần nhiều hơn một dòng hay tôi không thể làm cho chúng hoạt động.

Bất kể, nếu điều sau là đúng, có một cách giải quyết đơn giản; di chuyển nhiều dòng vào một tệp lô riêng biệt hoặc một chương trình con tệp lô. Tôi biết rằng cái sau hoạt động trong cả hai loại kịch bản.


0

Có lẽ hơi muộn, nhưng hy vọng nó sẽ thành công:

@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
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.