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

Mec*_*ash 15 cmd if-statement batch-file

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

使用的一个例子是:

IF EXIST somefile.txt IF EXIST someotherfile.txt SET var=somefile.txt,someotherfile.txt
Run Code Online (Sandbox Code Playgroud)

Mer*_*ham 32

是否有一个应遵循的特殊准则

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

但我是一名程序员.我习惯于编译,我习惯于调试.批处理文件未编译,您无法通过调试器运行它们,因此它们让我感到紧张.我建议你对你写的东西要特别严格,所以你可以非常肯定它会做你认为它做的事情.

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

我们来看看你的代码吧.

IF EXIST somefile.txt IF EXIST someotherfile.txt SET var=somefile.txt,someotherfile.txt
Run Code Online (Sandbox Code Playgroud)

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
)
Run Code Online (Sandbox Code Playgroud)

所以你把它们IF作为命令链接起来.

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

IF EXIST "somefile.txt" (
  IF EXIST "someotherfile.txt" (
    SET var="somefile.txt,someotherfile.txt"
  )
)
Run Code Online (Sandbox Code Playgroud)

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

此外,您还应该养成始终引用文件名并正确引用的习惯.还有在一些空话HELP FOR,并HELP SET会帮助你,除去多余的报价再次引用字符串时.

编辑

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

更好的方法是编写检查单个文件存在的子例程,如果指定的文件存在则附加到变量.然后只需为要检查的每个文件调用该子例程:

@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
Run Code Online (Sandbox Code Playgroud)


Aac*_*ini 11

上面Merlyn给出的解释非常完整.但是,我想详细说明编码标准.

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

SET AND=IF

IF EXIST somefile.txt %AND% EXIST someotherfile.txt SET var=somefile.txt,someotherfile.txt
Run Code Online (Sandbox Code Playgroud)

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

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

SET AND=IF
SET THEN=(
SET ELSE=) ELSE (
SET NOELSE=
SET ENDIF=)
SET BEGIN=(
SET END=)
SET RETURN=EXIT /B
Run Code Online (Sandbox Code Playgroud)

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%
Run Code Online (Sandbox Code Playgroud)

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

  • 1:这就像“数字绘画”版的编程哈哈 (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
Run Code Online (Sandbox Code Playgroud)

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