2011-02-13 44 views
78

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

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

Kỳ lạ là "GP Manager is up" cũng không "GP Manager down" được in khi chạy tệp lô.

+0

Có thể điều này có thể hữu ích: http://commandwindows.com/batchfiles-branching.htm – esaj

+0

Ya, điều đó có ích. DOS hút. Nếu tôi muốn sử dụng nhiều câu lệnh trong if hoặc else, tôi phải sử dụng && giữa các câu lệnh? hoặc là có một cách thanh lịch hơn? –

Trả lời

108

Bạn thực sự có thể đặt một khối câu lệnh để thực thi sau khi có điều kiện. Nhưng bạn có cú pháp sai. Các 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 dựng sẵn nào cho câu lệnh else-if. Bạn sẽ không may cần phải tạo các khối lồng nhau của các câu lệnh if để xử lý điều đó.


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


Mẫu mã 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 

Xin lưu ý một vài chi tiết cụ thể về mẫu mã của tôi:

  • Không gian 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 để tránh nhìn thấy tất cả các câu lệnh được in trên bàn đ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 bắt đầu cụ thể với echo.
  • Tôi đang sử dụng biến được xây dựng trong ERRORLEVEL giống như một thử nghiệm. Đọc thêm here
+0

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

+0

@jeb: Tôi nghĩ bạn có thể đã bỏ lỡ điểm. Sử dụng 'ERRORLEVEL' không phải là câu trả lời cho vấn đề của anh ta. Tôi chỉ đơn giản đăng một ví dụ về cú pháp thích hợp. * Có thể chấp nhận biểu mẫu * trong trường hợp này, giống như là 'if 0 == 0' hoặc bất kỳ biểu thức tầm thường nào khác. Nhưng thực sự, hãy chắc chắn rằng bạn hiểu sự khác biệt giữa biến môi trường '% ERRORLEVEL%' và 'ERRORLEVEL' nội bộ của bộ xử lý lệnh. Raymond Chen giải thích nó độc đáo [ở đây trên blog này] (http://blogs.msdn.com/b/oldnewthing/archive/2008/09/26/8965755.aspx). –

+0

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

12

Về mặt logic, câu trả lời của Cody nên 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 điều đó để hoạt động đúng với bất kỳ lệnh nào khác ngoài một lệnh 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 trữ 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ả mong đợi. Dưới đây là một ví dụ đơn giản đi:

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

này nên cung cấp var3 với giá trị sau:

blue_cheese 

nhưng thay vì mang lại:

_ 

bởi vì tất cả 3 lệnh được lưu trữ và thực hiện đồ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 nếu chỉ thực thi một lệnh - goto - và thêm một vài nhãn. Clunky của nó, và tôi không thích nó, 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 
+7

Sử dụng mở rộng trễ công việc: sử dụng: 'set var3 =! var1! _! var2!' – Dracorat

0

Có lẽ hơi muộn, nhưng hy vọng nó hellps:

@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 
-1

Thay vì mớ hỗn độn goto này, hãy thử sử dụng dấu và & hay dấu và đôi & & (có điều kiện để errorlevel 0) như tách lệnh.

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

cho %% b trong (yz defghijklmnopqrstuvwx) DO ( nếu tồn tại "%% b: \ Backup.cmd" %% b: & CALL "%% b: \ Backup .cmd " )

+0

Tại sao trái đất này lại bị giảm? Đây chính xác là những gì tôi cần. – ggb667

+0

@ 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 áp phích gốc. Nó liên quan đến câu trả lời của" vinniejohnson "(cũng bỏ qua vấn đề áp phích gốc). –

0

Tôi chạy ngang qua bài viết này trong kết quả trả về bởi tìm kiếm liên quan đến lệnh IF trong tập tin thực thi, và tôi không thể cưỡng lại cơ hội sửa sai quan niệm rằng khối IF bị giới hạn đơn lệnh. Sau đây là một phần của kịch bản lệnh Windows NT sản xuất chạy hàng ngày trên máy mà tôi đang soạn bài 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ẽ khối của hai hay nhiều dòng áp dụng riêng cho các kịch bản lệnh Windows NT (file .CMD), bởi vì tìm kiếm các kịch bản sản xuất thư mục của một ứng dụng được giới hạn hàng loạt trường cũ (.BAT) , chỉ tiết lộ một khối lệnh. Kể từ khi ứng dụng đã đi vào 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 cho dù đó là bởi vì tôi không cần nhiều hơn một dòng, hoặc rằng tôi không thể làm cho họ làm việc.

Bất kể, nếu điều sau là đúng, có 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 của tệp lô. Tôi biết rằng sau này hoạt động trong cả hai loại kịch bản.

Các vấn đề liên quan