使用超过1个IF语句时,是否应遵循特殊指南?它们应该分组吗?我应该使用括号来包装命令吗?
使用的一个例子是:
IF EXIST somefile.txt IF EXIST someotherfile.txt SET var=somefile.txt,someotherfile.txt
答案 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 FOR
和HELP 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