批处理文件忽略 FOR 循环内的 ELSE 语句

Batch file ignores ELSE statement inside a FOR loop

我目前正在创建一个批处理文件,用于解压缩它将在指定文件夹中检测到的所有存档。现在我正在尝试使用此代码检测指定文件夹中的存档文件:

@ECHO OFF
SETLOCAL
SETLOCAL EnableDelayedExpansion

SET quote="
SET cwdText=Current working directory: 
SET cwd=%cd%
SET fullCWD=%cwdText%%cwd%
SET path=%~dp0
SET types=file_types.txt
SET fullPath=%path%%types%

ECHO %fullCWD%
ECHO %fullPath%

:SPECIFYPATH
ECHO:
SET /P directory=Specify the full path location of the archive files:

IF "%cd%"=="%directory%" (
ECHO Specified location is already the current directory 
GOTO SPECIFYPATH
) ELSE (
PUSHD %directory%
CD
GOTO CHECKARCHIVES
)

:CHECKARCHIVES
FOR %%T IN (*.zip,*.rar,*.7z) DO (
IF EXIST %%T (
    ECHO Archive files detected
    GOTO EOF
) ELSE (
    ECHO Archive files not detected
    GOTO EOF
)
GOTO EOF
)

:EXTRACT
ECHO Extracting archive files

:EOF
PAUSE

我开始检查存档文件的部分位于 :CHECKARCHIVES 标签处。我现在遇到的问题是,每当我尝试指定一个没有存档文件的文件夹时,代码会立即跳转到 :EXTRACT 标签,而不会转到 ELSE 中的语句FOR 语句。有人可以解释为什么会这样吗?

我也尝试在第一个 IF 语句之后使用 IF NOT EXIST... 语句,但我仍然得到相同的行为。

这是您显示的代码的正确行为。如果没有存档文件,您将不会输入 'DO' 结构。你可以做这样的事情,或者更好的是在进入循环之前将计数器归零并在循环中递增它......然后如果你想要文件计数则在循环外询问它。

SET "Msg=Archive files not detected"
FOR %%T IN (*.zip,*.rar,*.7z) DO (
    SET "Msg=Archive files detected"
    REM do something else as needed
)
ECHO %Msg%

除了 RGuggisberg 的 post,您还可以在 for-loop.

之外使用不同的语法检查文件
for %%t in (*.zip,*.rar,*.7z) do set "myvar=%%t"
if defined myvar ( echo msg#1 Archive files DETECTED ) else ( echo msg#1 Archive files NOT detected )

for %%t in (*.zip,*.rar,*.7z) do (
  set "myvar=%%t"
)
if defined myvar ( echo msg#2 Archive files DETECTED ) else ( echo msg#2 Archive files NOT detected )

rem check the myvar by negation
if NOT defined myvar ( echo msg#3 Archive files NOT detected ) else ( echo msg#3 Archive files DETECTED )

for命令枚举的元素不包含通配符时,do子句中的代码被执行,for可替换参数将包含原样的元素。

但是当被枚举的元素包含一个通配符时,假定它需要被扩展并且检查文件系统是否存在匹配通配符表达式的文件。如果没有匹配的文件,则不会对该元素执行 do 子句中的代码。如果有文件匹配表达式,do 子句中的代码将不是针对表达式执行,而是针对每个匹配文件执行,并且 for 可替换参数将保存对当前文件的引用。

由于您的代码在匹配文件时使用通配符,因此 do 子句中的代码将针对每个文件执行(在您的情况下,仅针对找到的第一个文件,因为 goto), 并且, 如果没有任何匹配的文件, do 子句中的代码不会被执行, 所以else 子句无法到达.

但是,假设 for 不会检查文件系统,并且指示的元素按写入的方式迭代。您将遇到逻辑错误。内部 if 命令将检查是否存在仅匹配第一组的文件。如果未找到与第一组匹配的文件,则将 for 命令与 else 子句中的 goto 一起保留,因此不会检查其余组。

要保持​​ for 检查文件是否存在,更好的方法可能是

for %%T in (*.zip, *.rar, *.7z) do goto :extract
echo No archives found
goto eof

如果找到与任何通配符表达式匹配的任何文件,则 goto 将取消当前枚举并跳转到您的 :extract 标签。如果 for 循环结束并到达下一行,那是因为没有找到匹配的文件。