在批处理文件中使用多个IF语句

时间:2011-07-15 18:29:53

标签: batch-file if-statement cmd

使用超过1个IF语句时,是否应遵循特殊指南?它们应该分组吗?我应该使用括号来包装命令吗?

使用的一个例子是:

IF EXIST somefile.txt IF EXIST someotherfile.txt SET var=somefile.txt,someotherfile.txt

5 个答案:

答案 0 :(得分:30)

  

是否有应遵循的特殊准则

没有“标准”方式来处理批处理文件,因为他们的绝大多数作者和维护者要么不理解编程概念,要么他们认为它们不适用于批处理文件。

但我是一名程序员。我习惯于编译,我习惯于调试。批处理文件未编译,您无法通过调试器运行它们,因此它们让我感到紧张。我建议你对你写的内容要格外严格,所以你可以非常肯定它会按照你的想法做到。

有一些编码标准说:如果你写一个if语句,你必须使用大括号,即使你没有else条款。这样可以避免细微,难以调试的问题,并且可以明确地读取。我认为你无法将这种推理应用于批处理文件。

让我们来看看你的代码。

IF EXIST somefile.txt IF EXIST someotherfile.txt SET var=somefile.txt,someotherfile.txt

IF语法,来自命令HELP IF

IF [NOT] ERRORLEVEL number command
IF [NOT] string1==string2 command
IF [NOT] EXISTS filename command

...

IF EXIST filename (
  command
) ELSE (
  other command
)

所以你将IF作为命令链接。

如果您使用我上面提到的通用编码标准规则,您总是希望使用parens。以下是您为示例代码执行此操作的方法:

IF EXIST "somefile.txt" (
  IF EXIST "someotherfile.txt" (
    SET var="somefile.txt,someotherfile.txt"
  )
)

确保您干净地格式化,并进行某种形式的缩进。您可以在代码中执行此操作,并且应该在批处理脚本中执行此操作。

此外,您还应养成始终引用文件名并正确引用的习惯。 HELP FORHELP SET下有一些措辞可以帮助您在重新引用字符串时删除多余的引号。

修改

根据您的评论并重新阅读原始问题,您似乎想要构建一个以逗号分隔的文件列表。对于这种情况,您可以简单地使用一堆if / else语句,但这会导致一堆重复的逻辑,如果您有两个以上的文件,则根本不干净。

更好的方法是write a sub-routine检查单个文件是否存在,如果指定的文件存在则附加到变量。然后只需为要检查的每个文件调用该子例程:

@ECHO OFF
SETLOCAL

REM Todo: Set global script variables here
CALL :MainScript
GOTO :EOF

REM MainScript()
:MainScript
  SETLOCAL

  CALL :AddIfExists "somefile.txt" "%files%" "files"
  CALL :AddIfExists "someotherfile.txt" "%files%" "files"

  ECHO.Files: %files%

  ENDLOCAL
GOTO :EOF

REM AddIfExists(filename, existingFilenames, returnVariableName)
:AddIfExists
  SETLOCAL

  IF EXIST "%~1" (
    SET "result=%~1"
  ) ELSE (
    SET "result="
  )

  (
    REM Cleanup, and return result - concatenate if necessary
    ENDLOCAL

    IF "%~2"=="" (
      SET "%~3=%result%"
    ) ELSE (
      SET "%~3=%~2,%result%"
    )
  )
GOTO :EOF

答案 1 :(得分:11)

以上Merlyn的解释非常完整。但是,我想详细说明编码标准。

当链接多个IF时,在满足所有先前条件时执行最终命令;这相当于一个AND运算符。我偶尔会使用这种行为,但我清楚地通过一个名为AND的辅助Batch变量来表明我打算做什么:

SET AND=IF

IF EXIST somefile.txt %AND% EXIST someotherfile.txt SET var=somefile.txt,someotherfile.txt

当然,这不是真正的And运算符,不能与ELSE子句结合使用。这只是一个程序员帮助,可以提高很少使用的指令的易读性。

当我编写Batch程序时,我总是使用我设计的几个辅助变量,其唯一目的是编写更易读的代码。例如:

SET AND=IF
SET THEN=(
SET ELSE=) ELSE (
SET NOELSE=
SET ENDIF=)
SET BEGIN=(
SET END=)
SET RETURN=EXIT /B

这些变量有助于以更清晰的方式编写批处理程序,并有助于避免细微错误,正如Merlyn所说。例如:

IF EXIST "somefile.txt" %THEN%
  IF EXIST "someotherfile.txt" %THEN%
    SET var="somefile.txt,someotherfile.txt"
  %NOELSE%
  %ENDIF%
%NOELSE%
%ENDIF%

IF EXIST "%~1" %THEN%
  SET "result=%~1"
%ELSE%
  SET "result="
%ENDIF%

我甚至有变量可以帮助写入WHILE-DO和REPEAT-UNTIL之类的构造。这意味着Batch变量可以在某种程度上用作预处理器值。

答案 2 :(得分:5)

批处理文件的逻辑功能非常有限,所以你希望得到的最好的解决方法是间接实现你想要的。这并不是说你应该觉得他们不如真正的语言 - 他们仍然需要同样注重细节和手动调试作为一个真正的应用程序。只是你需要更加努力地让他们以健壮的方式做你想做的事。

对于OP的问题,听起来您需要存在两个特定文件。只需使用计数:

IF EXIST somefile.txt (
    set /a file1_status=1
)

IF EXIST someotehrfile.txt (
    set /a file2_status=1
)

set /a file_status_result=file1_status + file2_status

if %file_status_result% equ 2 (
    goto somefileexists
)

goto exit

:somefileexists
IF EXIST someotherfile.txt SET var=...

:exit

我的示例使用3个变量,但如果文件存在,您只需将1添加到file_result_status即可。但是,如果您希望稍后在批处理文件中进行更精细的控制,则可以像我一样记录每个文件的结果,这样您就不必一直检查文件是否存在。

答案 3 :(得分:3)

IF EXIST "somefile.txt" (
  IF EXIST "someotherfile.txt" (
    SET var="somefile.txt","someotherfile.txt"
  )
) ELSE (
  CALL :SUB
)
:SUB
ECHO Sorry... nothin' there.
GOTO:EOF

这可行吗?

SETLOCAL ENABLEDELAYEDEXPANSION
IF EXIST "somefile.txt" (
  SET var="somefile.txt"
  IF EXIST "someotherfile.txt" (
    SET var=!var!,"someotherfile.txt"
  )
) ELSE (
  IF EXIST "someotherfile.txt" (
    SET var="someotherfile.txt"
  ) ELSE (
  GOTO:EOF
  )
)

答案 4 :(得分:1)

您可以使用goto

来构建批处理文件
IF EXIST somefile.txt goto somefileexists
goto exit

:somefileexists
IF EXIST someotherfile.txt SET var=...

:exit