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

时间:2015-10-15 03:05:08

标签: windows batch-file command-prompt

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

@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 NOT EXIST...声明。有人可以解释为什么会这样吗?

我也尝试在第一个IF语句之后使用buildscript { def root = file('.').toString(); // We have to seek through, since groovy/gradle introduces // a lot of abstraction that we see in the trace as extra frames. // Fortunately, the first frame in the build dir is always going // to be this script. buildscript.metaClass.__script__ = file( Thread.currentThread().stackTrace.find { ste -> ste.fileName?.startsWith root }.fileName ) // later, still in buildscript def libDir = "${buildscript.__script__.parent}/lib" classpath files("${libDir}/custom-plugin.jar") } // This is important to do if you intend to use this path outside of // buildscript{}, since everything else is pretty asynchronous, and // they all share the buildscript object. def __buildscripts__ = buildscript.__script__.parent; 语句,但我仍然会遇到相同的行为。

3 个答案:

答案 0 :(得分:4)

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

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

如果您的代码使用通配符,如果存在匹配的文件,则会为每个文件执行do子句中的代码(在您的情况下,仅针对找到的第一个文件,因为goto) ,并且,如果没有任何匹配的文件,则不执行do子句中的代码,因此无法访问else子句。

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

要让for检查文件的存在,可以采用更好的方法

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

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

答案 1 :(得分:1)

这是您显示的代码的正确行为。如果没有存档文件,则不会进入“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%

答案 2 :(得分:0)

除了RGuggisberg的帖子之外,您可以使用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 )