迭代文件并仅在其使用批处理文件的 zip 文件夹时提取

Iterating through the files and extracting only if its a zip folder using a batch file

我需要遍历当前文件夹中的所有文件并仅在其为 zip 文件时将其解压缩。所以我写了下面的批处理脚本。但是我收到一条错误消息

"=="."zip" was unexpected at this time

下面是我写的批处理脚本

@echo off
cd /d %~dp0
for /r %%i in (*) do if %%i "%Extension%"==".zip" (
setlocal
cd /d %~dp0
Call :UnZipFile "G:\NewUpdates\ExtractedStuff" %%i
exit /b

:UnZipFile <ExtractTo> <newzipfile>
set vbs="%temp%\_.vbs"
if exist %vbs% del /f /q %vbs%
>%vbs%  echo Set fso = CreateObject("Scripting.FileSystemObject")
>>%vbs% echo If NOT fso.FolderExists(%1) Then
>>%vbs% echo fso.CreateFolder(%1)
>>%vbs% echo End If
>>%vbs% echo set objShell = CreateObject("Shell.Application")
>>%vbs% echo set FilesInZip=objShell.NameSpace(%2).items
>>%vbs% echo objShell.NameSpace(%1).CopyHere(FilesInZip)
>>%vbs% echo Set fso = Nothing
>>%vbs% echo Set objShell = Nothing
cscript //nologo %vbs%
if exist %vbs% del /f /q %vbs%
)
pause

我在这里做错了什么?请指教

我的建议是通过在 for 命令中过滤它们来简化 zip 文件的搜索,而不是检查文件扩展名

使用以下命令:

for /f "tokens=*" %%a in ('dir /a:-d /b ^| findstr /r ".zip$"') do echo %%a

以上命令将列出您目录中的所有 zip 文件,现在您可以随心所欲地使用它们了

希望这对您有所帮助。

你正在读取一个未定义的变量%Extension%,你在if语句中==的左边有两个表达式,这是一个语法错误。

要获取由 for 循环迭代的项目的文件扩展名,请使用 ~x 修饰符(在命令提示符下键入 for /? 以了解更多相关信息),就像代码中的 %%~xi

if /i "%%~xi"==".zip" ( ... )

/i 开关使比较不区分大小写,这里推荐这样做,因为 Windows 以相同的方式处理文件名。


但是,在您的情况下,您根本不需要 if 语句来检查文件扩展名,因为您可以让 for 完成这项工作:

for /r %%i in (*.zip) do ( ... )

此循环仅遍历 *.zip 个文件。


您的代码中还有一个问题:子例程 :UnZipFile 是循环体的一部分,因此循环内部有 and exit /b

子例程必须在循环之外。执行call时,括号内代码块的当前上下文在子例程中是未知的,因此一旦出现循环结束)就不会认为它已经结束,而是一种语法出现错误。因此,您需要将 ) 从最底部移动到新行 before exit /b (如果将其放在之后,exit 命令将打破循环)。

因为你的循环中有 setlocal,你还需要放置 endlocal(紧接在 ) 之前)以免超过 setlocal 嵌套限制。但是,如果您在循环内使用完整路径,则不需要 setlocal/endlocal。相反,我会将 setlocal/endlocal 移动到子例程中以本地化其中使用的环境变量。


我不确定您是否打算更改为 cd /d %~dp0 存储脚本的目录,但我认为您需要循环中当前迭代的 *.zip 文件的完整路径, 正确的?如果是这样,请删除 cd 命令并在 call 命令行中使用 %%~fi


最后,整个代码的引用不是最优的。例如,引用文件路径和名称始终是个好主意,因为它们可能包含空格或一些其他字符,这些字符被命令解释器视为定界符或具有其他特殊含义。

同样在子例程中,您应该引用作为参数提供的路径,并以 "%~1" 的形式访问它们,例如,以正确引用它们(键入 call /? 以查看 ~ 删除可能由命令行传递的周围引号)。

最好的set语法是:set "vbs=%temp%\_.vbs";所以引号不会成为值的一部分,你总是 one 放置引号的地方 - 即当 reading (扩展)变量, 比如 "%vbs%".


最后,我建议您使用缩进,这样代码会变得更加清晰易读和可维护。


固定代码如下:

@echo off
cd /d %~dp0
for /r %%i in ("*.zip") do (
    Call :UnZipFile "G:\NewUpdates\ExtractedStuff" "%%~fi"
)
exit /b

:UnZipFile <ExtractTo> <newzipfile>
    setlocal
    set vbs="%temp%\_.vbs"
    if exist "%vbs%" del /f /q "%vbs%"
     >"%vbs%" echo Set fso = CreateObject("Scripting.FileSystemObject")
    >>"%vbs%" echo If NOT fso.FolderExists("%~1") Then
    >>"%vbs%" echo fso.CreateFolder("%~1")
    >>"%vbs%" echo End If
    >>"%vbs%" echo set objShell = CreateObject("Shell.Application")
    >>"%vbs%" echo set FilesInZip=objShell.NameSpace("%~2").items
    >>"%vbs%" echo objShell.NameSpace("%~1").CopyHere(FilesInZip)
    >>"%vbs%" echo Set fso = Nothing
    >>"%vbs%" echo Set objShell = Nothing
    cscript //nologo "%vbs%"
    if exist "%vbs%" del /f /q "%vbs%"
    endlocal
    pause