2015-10-15 170 views
0

我当前正在创建一个批处理文件,该文件解压缩它将在指定文件夹中检测到的所有存档。现在我想使用此代码的指定文件夹内检测存档文件:批处理文件忽略FOR循环内的ELSE语句

@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标签,并且不会转到FOR语句中的ELSE语句。有人可以解释为什么这样吗?

我也试过在第一个IF声明后面使用IF NOT EXIST...声明,但我仍然得到相同的行为。

回答

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循环结束并且到达下一行,那是因为没有找到匹配的文件。

+0

我明白了。所以这意味着批处理文件环境中的'FOR'语句更像是一个'IF'语句的迭代版本,而不像我们通常在C++等编程语言中知道的那样? – Jairo

+0

我不会说迭代'if';你可以认为它像'for each',遍历所有匹配的文件... – aschipfl

+0

@Jairo,'for'只是[*“globs”*](https://en.wikipedia.org/wiki/Glob_% 28编程%29)指定组中的元素。 –

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% 
+0

是不是行'SET'Msg =没有检测到存档文件“'没有使用'IF'语句,将触发它和'FOR'循环语句?如果我问这个,我很抱歉。这是我第一次开发批处理文件。 另一个我曾经想过的问题是,如果我使用我的代码,并且您建议的是我可能会添加ZIP,RAR和7z以外的其他存档文件类型。有没有办法让我做到这一点?我正在考虑使用一个文本文件,其中列举了所有的归档文件类型,并使用该文件检查目录/文件夹中是否存在任何文件。 – Jairo

+0

1.不,它不是无用的,它预先初始化'Msg';如果遇到档案文件,'for'koop正在迭代,'Msg'被更新/覆盖; 2.关于档案类型列表:通过评论扩展原始问题的范围并不是一个好主意;相反,你应该发表一个新的问题,涵盖... – aschipfl

+0

@aschipfl我明白。关于我的其他问题,我会发布一个新问题。 – Jairo

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)