已达到最大 setlocal 递归级别 & endlocal。解决方法?
Maximum setlocal recursion level reached & endlocal. Workaround?
我有一段代码被执行了 0-100,000 次。有问题的块显示如下:
FOR /R %%f IN (*.*) DO (
CLS
ECHO Del 2.0
ECHO Files Done^: !FILES_DONE! / !FILES_TOTAL!
ECHO Missing^: !FILES_MISSING!
SETLOCAL DisableDelayedExpansion
SET "FILES_TEMP=%%f"
SETLOCAL EnableDelayedExpansion
IF EXIST "!FILES_TEMP!" (
!DELITE! -p 13 -q "!FILES_TEMP!" >NUL
SET /A FILES_DONE += 1
) ELSE (
SET /A FILES_MISSING += 1
)
)
在此块中:!FILES_DONE!
、!FILES_TOTAL!
和 !FILES_MISSING!
都是整数变量。
!DELITE!
是对可执行文件的引用:“!CD!\_sdelete.exe”,其中“!CD!”是执行批处理的根文件夹。
注意:请注意,打开 DelayedExpansion on/off 是必要的,因为我需要捕获可能包含或不包含特殊字符的文件名,例如:“!”和“^”。
所以我的问题是:如何重新格式化此代码块以不抛出“已达到最大递归级别”错误? (我知道这个问题被问的频率有多高,这只是我问题的一半,所以请耐心等待)
其次,有人可以解释一下这段代码在本地环境中的作用吗?
SETLOCAL EnableDelayedExpansion
FOR /R %%f IN (*.*) DO (
ECHO !FILES_DONE! / !FILES_TOTAL!
ENDLOCAL & (
SET "FILES_TEMP=%%f"
)
[etc...]
)
例如,一旦它循环了一次代码,'endlocal' 是否仍然有效,还是会恢复,因为它是一个新循环?此外,它是否有助于达到最大 Setlocal 级别?
###########################################################################################
Del 2.0 - 完整文件内容供任何想使用它的人使用
注意:如果有人想要 Del Batch 的更新副本,请给我发消息;目前为V3.0-R0,需要使用sdelete.exe command-line utility from Microsoft。我最终可能会将其托管在一个网站上,作为任何想要安全删除程序的人的免费扩展。
@ECHO OFF
SETLOCAL EnableDelayedExpansion
TITLE Del 2.0
GOTO PRECHECK
:PRECHECK
ECHO Del 2.0
ECHO Checking...
IF NOT EXIST "!CD!\To-Do" (
ECHO To-Do Folder Not Found
ECHO.
ECHO Nothing To Delete
PAUSE >NUL
GOTO END
)
IF NOT EXIST "!CD!\_sdelete.exe" (
ECHO SDelete Program Not Found
ECHO.
ECHO Core File "_sdelete.exe" Missing
PAUSE >NUL
GOTO END
) ELSE (
ATTRIB +S +H "!CD!\_sdelete.exe" >NUL
)
TIMEOUT /T 1 /NOBREAK >NUL
GOTO SETVARS
:SETVARS
CLS
ECHO Del 2.0
ECHO Writing Variables...
SET TAB=
SET FILES_TEMP=0
SET FILES_TOTAL=0
SET FILES_DONE=0
SET FILES_MISSING=0
SET ROOTCD=!CD!
SET HOMECD=!CD!\To-Do
SET DELITE="!CD!\_sdelete.exe"
TIMEOUT /T 1 /NOBREAK >NUL
GOTO START
:START
CLS
ECHO Del 2.0
ECHO Starting...
ATTRIB -S -H ** /S /D
CD To-Do
TIMEOUT /T 1 /NOBREAK >NUL
CLS
ECHO Del 2.0
ECHO Counting Files...
FOR /R %%f IN (**) DO (
CLS
SET /A FILES_TOTAL += 1
ECHO Del 2.0
ECHO Files Found^: !FILES_TOTAL!
)
TIMEOUT /T 1 /NOBREAK >NUL
GOTO ERASEFILES
:ERASEFILES
CLS
ECHO Del 2.0
ECHO Erasing Files...
SETLOCAL DisableDelayedExpansion
FOR /R %%f IN (*.*) DO (
SET "FILES_TEMP=%%f"
CALL :SUBERASE
)
GOTO FINISHERASE
:SUBERASE
CLS
ECHO Del 2.0
ECHO Files Done^: %FILES_DONE% / %FILES_TOTAL%
ECHO Missing^: %FILES_MISSING%
IF EXIST "%FILES_TEMP%" (
%DELITE% -p 13 -q "%FILES_TEMP%" >NUL
SET /A FILES_DONE += 1
) ELSE (
SET /A FILES_MISSING += 1
)
EXIT /B
:FINISHERASE
SETLOCAL EnableDelayedExpansion
CLS
ECHO Del 2.0
ECHO Files Done^: !FILES_DONE! / !FILES_TOTAL!
ECHO Missing^: !FILES_MISSING!
TIMEOUT /T 3 /NOBREAK >NUL
GOTO CLEANUP
:CLEANUP
CLS
ECHO Del 2.0
ECHO Cleaning Up...
IF !FILES_MISSING! EQU 0 (
FOR /D %%f in (*.*) DO (
SETLOCAL DisableDelayedExpansion
SET "FILES_TEMP=%%f"
SETLOCAL EnableDelayedExpansion
RD "!FILES_TEMP!" /S /Q >NUL
)
)
TIMEOUT /T 1 /NOBREAK >NUL
GOTO END
:END
CLS
ECHO Del 2.0
ECHO Complete^^!
TIMEOUT /T 3 /NOBREAK >NUL
EXIT
保持Delayed Expansion disabled using call
command如下:
@ECHO OFF
SETLOCAL EnableExtensions DisableDelayedExpansion
FOR /R %%f IN (*.*) DO (
SET "FILES_TEMP=%%f"
CALL :doAll
)
goto :skipSubroutine
:doAll
CLS
ECHO Del 2.0
ECHO Files Done^: %FILES_DONE% / %FILES_TOTAL%
ECHO Missing^: %FILES_MISSING%
IF EXIST "%FILES_TEMP%" (
%DELITE% -p 13 -q "%FILES_TEMP%" >NUL
SET /A FILES_DONE += 1
) ELSE (
SET /A FILES_MISSING += 1
)
goto :eof
:skipSubroutine
如果 FILES_TEMP
变量 需要 Delayed Expansion enabled 那么 :doAll
子例程可能如下所示(注意 ENDLOCAL
命令是使用两次以在脚本范围内正确更新变量 FILES_DONE
和 FILES_MISSING
):
:doAll
CLS
ECHO Del 2.0
ECHO Files Done^: %FILES_DONE% / %FILES_TOTAL%
ECHO Missing^: %FILES_MISSING%
SETLOCAL EnableDelayedExpansion
IF EXIST "!FILES_TEMP!" (
%DELITE% -p 13 -q "!FILES_TEMP!" >NUL
ENDLOCAL
SET /A FILES_DONE += 1
) ELSE (
ENDLOCAL
SET /A FILES_MISSING += 1
)
goto :eof
我有一段代码被执行了 0-100,000 次。有问题的块显示如下:
FOR /R %%f IN (*.*) DO (
CLS
ECHO Del 2.0
ECHO Files Done^: !FILES_DONE! / !FILES_TOTAL!
ECHO Missing^: !FILES_MISSING!
SETLOCAL DisableDelayedExpansion
SET "FILES_TEMP=%%f"
SETLOCAL EnableDelayedExpansion
IF EXIST "!FILES_TEMP!" (
!DELITE! -p 13 -q "!FILES_TEMP!" >NUL
SET /A FILES_DONE += 1
) ELSE (
SET /A FILES_MISSING += 1
)
)
在此块中:!FILES_DONE!
、!FILES_TOTAL!
和 !FILES_MISSING!
都是整数变量。
!DELITE!
是对可执行文件的引用:“!CD!\_sdelete.exe”,其中“!CD!”是执行批处理的根文件夹。
注意:请注意,打开 DelayedExpansion on/off 是必要的,因为我需要捕获可能包含或不包含特殊字符的文件名,例如:“!”和“^”。
所以我的问题是:如何重新格式化此代码块以不抛出“已达到最大递归级别”错误? (我知道这个问题被问的频率有多高,这只是我问题的一半,所以请耐心等待)
其次,有人可以解释一下这段代码在本地环境中的作用吗?
SETLOCAL EnableDelayedExpansion
FOR /R %%f IN (*.*) DO (
ECHO !FILES_DONE! / !FILES_TOTAL!
ENDLOCAL & (
SET "FILES_TEMP=%%f"
)
[etc...]
)
例如,一旦它循环了一次代码,'endlocal' 是否仍然有效,还是会恢复,因为它是一个新循环?此外,它是否有助于达到最大 Setlocal 级别?
###########################################################################################
Del 2.0 - 完整文件内容供任何想使用它的人使用
注意:如果有人想要 Del Batch 的更新副本,请给我发消息;目前为V3.0-R0,需要使用sdelete.exe command-line utility from Microsoft。我最终可能会将其托管在一个网站上,作为任何想要安全删除程序的人的免费扩展。
@ECHO OFF
SETLOCAL EnableDelayedExpansion
TITLE Del 2.0
GOTO PRECHECK
:PRECHECK
ECHO Del 2.0
ECHO Checking...
IF NOT EXIST "!CD!\To-Do" (
ECHO To-Do Folder Not Found
ECHO.
ECHO Nothing To Delete
PAUSE >NUL
GOTO END
)
IF NOT EXIST "!CD!\_sdelete.exe" (
ECHO SDelete Program Not Found
ECHO.
ECHO Core File "_sdelete.exe" Missing
PAUSE >NUL
GOTO END
) ELSE (
ATTRIB +S +H "!CD!\_sdelete.exe" >NUL
)
TIMEOUT /T 1 /NOBREAK >NUL
GOTO SETVARS
:SETVARS
CLS
ECHO Del 2.0
ECHO Writing Variables...
SET TAB=
SET FILES_TEMP=0
SET FILES_TOTAL=0
SET FILES_DONE=0
SET FILES_MISSING=0
SET ROOTCD=!CD!
SET HOMECD=!CD!\To-Do
SET DELITE="!CD!\_sdelete.exe"
TIMEOUT /T 1 /NOBREAK >NUL
GOTO START
:START
CLS
ECHO Del 2.0
ECHO Starting...
ATTRIB -S -H ** /S /D
CD To-Do
TIMEOUT /T 1 /NOBREAK >NUL
CLS
ECHO Del 2.0
ECHO Counting Files...
FOR /R %%f IN (**) DO (
CLS
SET /A FILES_TOTAL += 1
ECHO Del 2.0
ECHO Files Found^: !FILES_TOTAL!
)
TIMEOUT /T 1 /NOBREAK >NUL
GOTO ERASEFILES
:ERASEFILES
CLS
ECHO Del 2.0
ECHO Erasing Files...
SETLOCAL DisableDelayedExpansion
FOR /R %%f IN (*.*) DO (
SET "FILES_TEMP=%%f"
CALL :SUBERASE
)
GOTO FINISHERASE
:SUBERASE
CLS
ECHO Del 2.0
ECHO Files Done^: %FILES_DONE% / %FILES_TOTAL%
ECHO Missing^: %FILES_MISSING%
IF EXIST "%FILES_TEMP%" (
%DELITE% -p 13 -q "%FILES_TEMP%" >NUL
SET /A FILES_DONE += 1
) ELSE (
SET /A FILES_MISSING += 1
)
EXIT /B
:FINISHERASE
SETLOCAL EnableDelayedExpansion
CLS
ECHO Del 2.0
ECHO Files Done^: !FILES_DONE! / !FILES_TOTAL!
ECHO Missing^: !FILES_MISSING!
TIMEOUT /T 3 /NOBREAK >NUL
GOTO CLEANUP
:CLEANUP
CLS
ECHO Del 2.0
ECHO Cleaning Up...
IF !FILES_MISSING! EQU 0 (
FOR /D %%f in (*.*) DO (
SETLOCAL DisableDelayedExpansion
SET "FILES_TEMP=%%f"
SETLOCAL EnableDelayedExpansion
RD "!FILES_TEMP!" /S /Q >NUL
)
)
TIMEOUT /T 1 /NOBREAK >NUL
GOTO END
:END
CLS
ECHO Del 2.0
ECHO Complete^^!
TIMEOUT /T 3 /NOBREAK >NUL
EXIT
保持Delayed Expansion disabled using call
command如下:
@ECHO OFF
SETLOCAL EnableExtensions DisableDelayedExpansion
FOR /R %%f IN (*.*) DO (
SET "FILES_TEMP=%%f"
CALL :doAll
)
goto :skipSubroutine
:doAll
CLS
ECHO Del 2.0
ECHO Files Done^: %FILES_DONE% / %FILES_TOTAL%
ECHO Missing^: %FILES_MISSING%
IF EXIST "%FILES_TEMP%" (
%DELITE% -p 13 -q "%FILES_TEMP%" >NUL
SET /A FILES_DONE += 1
) ELSE (
SET /A FILES_MISSING += 1
)
goto :eof
:skipSubroutine
如果 FILES_TEMP
变量 需要 Delayed Expansion enabled 那么 :doAll
子例程可能如下所示(注意 ENDLOCAL
命令是使用两次以在脚本范围内正确更新变量 FILES_DONE
和 FILES_MISSING
):
:doAll
CLS
ECHO Del 2.0
ECHO Files Done^: %FILES_DONE% / %FILES_TOTAL%
ECHO Missing^: %FILES_MISSING%
SETLOCAL EnableDelayedExpansion
IF EXIST "!FILES_TEMP!" (
%DELITE% -p 13 -q "!FILES_TEMP!" >NUL
ENDLOCAL
SET /A FILES_DONE += 1
) ELSE (
ENDLOCAL
SET /A FILES_MISSING += 1
)
goto :eof