如何在批处理文件中使用if-else结构?

165

我对批处理文件中的if-else结构有疑问。每个命令都可以单独运行,但我无法安全地使用“if-else”块,因此程序的这些部分不起作用。我该如何使这些部分运行?谢谢。

IF %F%==1 IF %C%==1 (
    ::copying the file c to d
    copy "%sourceFile%" "%destinationFile%"
    )
ELSE IF %F%==1 IF %C%==0 (
    ::moving the file c to d
    move "%sourceFile%" "%destinationFile%"
    )

ELSE IF %F%==0 IF %C%==1 (
    ::copying a directory c from d, /s:  boş olanlar hariç, /e:boş olanlar dahil
    xcopy "%sourceCopyDirectory%" "%destinationCopyDirectory%" /s/e
    )
ELSE IF %F%==0 IF %C%==0 (
    ::moving a directory
    xcopy /E "%sourceMoveDirectory%" "%destinationMoveDirectory%"
    rd /s /q "%sourceMoveDirectory%"
    )

我的问题表述清楚吗?我逐行阅读,但感觉它们是并排的。 - eponymous
4
你好,欢迎来到Stack Overflow!要创建代码块,请将相关文本突出显示,然后单击“{}”按钮;它有助于使帖子更易读,并避免标记方面的一些问题。回答你的问题,现在可以了!当编写问题时,下方会显示预览,以便您在发布后查看其外观。 - Ben
1
非常感谢您的解释。我将使用这些方法。 - eponymous
如果有人想将多个命令放在一个if语句中,也可以参考这篇文章:https://stackoverflow.com/questions/13692916/unable-to-echo-user-input-values-to-file-in-batch-script - yu yang Jian
8个回答

131

你的语法不正确。你不能使用 ELSE IF。看起来你其实也不需要它。只需使用多个 IF 语句:

IF %F%==1 IF %C%==1 (
    ::copying the file c to d
    copy "%sourceFile%" "%destinationFile%"
    )

IF %F%==1 IF %C%==0 (
    ::moving the file c to d
    move "%sourceFile%" "%destinationFile%"
    )

IF %F%==0 IF %C%==1 (
    ::copying a directory c from d, /s:  boş olanlar hariç, /e:boş olanlar dahil
    xcopy "%sourceCopyDirectory%" "%destinationCopyDirectory%" /s/e
    )

IF %F%==0 IF %C%==0 (
    ::moving a directory
    xcopy /E "%sourceMoveDirectory%" "%destinationMoveDirectory%"
    rd /s /q "%sourceMoveDirectory%"
    )

很好的批处理文件参考资料:http://ss64.com/nt/if.html


3
请纠正我如果我错了,但我认为您不能在多个if条件中使用&&,看看我的替代语法? - Bali C
如果我的if条件像这样:“IF%F%== 0”,它可以安全运行,但是当我添加&&时它不会运行。如何在if语句中使用两个条件? - eponymous
1
@aprogrammer,看看我的例子。如果你有多个条件,请使用 IF condition1 IF condition2 - James Hill
我想解释一下我的代码;我在每个if块之外添加了“else块”,除了第一个“if块”。谢谢你的回答。 - eponymous
5
你的意思是你不能使用ELSE IF吗?在Win7下它可以正常工作。参考示例:http://paste2.org/G8tMae92 - bryc
显示剩余3条评论

65

我认为在问题和部分答案中存在一些混淆,关于DOS中这个伪代码的含义:IF A IF B X ELSE Y。它不意味着IF(A和B)THEN X ELSE Y,而是意味着IF A(IF B THEN X ELSE Y)。如果A的测试失败,则整个内部if-else将被忽略。

正如其中一个答案提到的那样,在这种情况下,只有一个测试可以成功,所以'else'是不需要的,但当然这仅适用于此示例,它并不是执行if-else的通用解决方案。

有很多方法可以解决这个问题。以下是一些想法,所有这些方法都相当丑陋,但是嘿,这是(或者至少曾经是)DOS!

@echo off

set one=1
set two=2

REM Example 1

IF %one%_%two%==1_1 (
   echo Example 1 fails
) ELSE IF %one%_%two%==1_2 (
   echo Example 1 works correctly
) ELSE (
    echo Example 1 fails
)

REM Example 2

set test1result=0
set test2result=0

if %one%==1 if %two%==1 set test1result=1
if %one%==1 if %two%==2 set test2result=1

IF %test1result%==1 (
   echo Example 2 fails
) ELSE IF %test2result%==1 (
   echo Example 2 works correctly
) ELSE (
    echo Example 2 fails
)

REM Example 3

if %one%==1 if %two%==1 (
   echo Example 3 fails
   goto :endoftests
)
if %one%==1 if %two%==2 (
   echo Example 3 works correctly
   goto :endoftests
)
echo Example 3 fails
)
:endoftests

我认为前两个“set”不需要百分号;应该是“set one=1”。 - Geoff

13
据我所知,在批处理中你不能像其他语言那样使用if else,而必须使用嵌套的if。使用嵌套的if,你的批处理将如下所示:
IF %F%==1 IF %C%==1(
    ::copying the file c to d
    copy "%sourceFile%" "%destinationFile%"
    ) ELSE (
        IF %F%==1 IF %C%==0(
        ::moving the file c to d
        move "%sourceFile%" "%destinationFile%"
        ) ELSE (
            IF %F%==0 IF %C%==1(
            ::copying a directory c from d, /s:  boş olanlar hariç, /e:boş olanlar dahil
            xcopy "%sourceCopyDirectory%" "%destinationCopyDirectory%" /s/e
            ) ELSE (
                IF %F%==0 IF %C%==0(
                ::moving a directory
                xcopy /E "%sourceMoveDirectory%" "%destinationMoveDirectory%"
                rd /s /q "%sourceMoveDirectory%"
                )
            )
        )
    )

或者像 James 建议的那样,将你的 if 连接起来,不过我认为正确的语法是:

IF %F%==1 IF %C%==1(
    ::copying the file c to d
    copy "%sourceFile%" "%destinationFile%"
    )

1
在类C语言中,“if else”只是一个嵌套的“if”。在批处理文件中,您也不必使用块来嵌套它们。 - Joey
@Joey,我不太明白。我知道else if组合只是一个嵌套的if,但我认为你不能像在C语言中那样在批处理中同时使用这些关键字。 - Bali C
嗯,我还是无法让它正常工作,但我相信你的话,你知道你在说什么,我会将这个答案留成长篇版的 :) - Bali C
谢谢您的回答,但是它们中没有一个在我的代码中运行。 - eponymous
另一个例子: 如果1==1(echo 1)否则(如果1==1(echo 2)否则(echo 3)) - JohnP2

7

这是我如何处理 if else if 的情况:

if %env%==dev ( 
    echo "dev env selected selected"
) else (
    if %env%==prod (
        echo "prod env selected"
    )
)

注意,这与其他编程语言(如C++或Java)中的if-elseif块不同,但它将完成您需要做的工作。


2
我相信您可以使用类似以下的内容:

我相信您可以使用类似以下的内容:

if ___ (

do this

) else if ___ (

do this

)

32
第二个条件语句中的陈述不应该是“做那个吗(do that)”? - bvj
9
不,不,你理解错了。应该是“执行foo”和“执行bar”。 - yyny
当你写 IF (test) (command) ELSE IF (test) (command) 时,你暗示了 IF (test) (command) ELSE (IF (test) (command))。这有时可能有效,但如果你认为它是 DOS 中可接受的实际编程结构,那么当它失败时进行故障排除将会非常麻烦。 - Tim

1
稍晚了一些,但对于复杂的if条件可能仍然有用,因为我想添加一个“done”参数来保持if-then-else结构:
set done=0
if %F%==1 if %C%==0 (set done=1 & echo found F=1 and C=0: %F% + %C%)
if %F%==2 if %C%==0 (set done=1 & echo found F=2 and C=0: %F% + %C%)
if %F%==3 if %C%==0 (set done=1 & echo found F=3 and C=0: %F% + %C%)
if %done%==0 (echo do something)

0

IF...ELSE IF结构在批处理文件中非常有效,特别是当您在每个IF行上只使用一个条件表达式时:

IF %F%==1 (
    ::copying the file c to d
    copy "%sourceFile%1" "%destinationFile1%"
) ELSE IF %F%==0 (
    ::moving the file e to f
    move "%sourceFile2%" "%destinationFile2%" )

在你的例子中,你使用了 IF...AND...IF 类型的结构,其中必须同时满足两个条件。在这种情况下,你仍然可以使用 IF...ELSE IF 结构,但是需要加上额外的括号以避免下一个 ELSE 条件的不确定性:
IF %F%==1 (IF %C%==1 (
    ::copying the file c to d
    copy "%sourceFile1%" "%destinationFile1%" )
) ELSE IF %F%==1 (IF %C%==0 (
    ::moving the file e to f
    move "%sourceFile2%" "%destinationFile2%"))

上述结构等同于:

IF %F%==1 (
    IF %C%==1 (
    ::copying the file c to d
    copy "%sourceFile1%" "%destinationFile1%"
    ) ELSE IF %C%==0 (
    ::moving the file e to f
    move "%sourceFile2%" "%destinationFile2%"))

处理批处理命令序列取决于CMD.exe解析顺序。只需确保您的结构遵循该逻辑顺序,通常情况下它就可以正常工作。如果Cmd.exe能够在没有错误的情况下处理您的批处理脚本,则意味着这是正确的(即由您的操作系统Cmd.exe版本支持的结构),即使有人说过其他话也是如此。


0
这是我的代码示例,用于 if..else..if,它执行以下操作:
提示用户输入进程名称。
如果进程名称无效,则向用户写入信息。
Error : The Processor above doesn't seem to be exist 

如果进程名称是services
那么就向用户写入信息

Error : You can't kill the Processor above 

如果进程名是有效的且不是服务
那么它会写入用户

进程已经通过taskill被杀死了

因此我将其命名为进程杀手.bat
以下是我的代码:

@echo off

:Start
Rem preparing the batch  
cls
Title Processor Killer
Color 0B
Echo Type Processor name to kill It (Without ".exe")
set /p ProcessorTokill=%=%  

:tasklist
tasklist|find /i "%ProcessorTokill%.exe">nul & if errorlevel 1 (
REM check if the process name is invalid 
Cls 
Title %ProcessorTokill% Not Found
Color 0A
echo %ProcessorTokill%
echo Error : The Processor above doesn't seem to be exist    

) else if %ProcessorTokill%==services (
REM check if the process name is services and doesn't kill it
Cls 
Color 0c
Title Permission denied 
echo "%ProcessorTokill%.exe"
echo Error : You can't kill the Processor above 

) else (
REM if the process name is valid and not services
Cls 
Title %ProcessorTokill% Found
Color 0e
echo %ProcessorTokill% Found
ping localhost -n 2 -w 1000>nul
echo Killing %ProcessorTokill% ...
taskkill /f /im %ProcessorTokill%.exe /t>nul
echo %ProcessorTokill% Killed...
)

pause>nul



REM If else if Template
REM if thing1 (
REM Command here 2 ! 
REM ) else if thing2 (
REM command here 2 !
REM ) else (
REM command here 3 !
REM )

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接