迭代文件并仅在其使用批处理文件的 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
我需要遍历当前文件夹中的所有文件并仅在其为 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