2016-06-11 28 views
3

我有一段代碼在0-100,000次的任何地方執行。有問題的塊顯示爲這樣:達到&endlocal的最大setlocal遞歸級別。解決方法?

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是必要的,因爲我需要捕獲文件名,該文件名可能包含或不包含特殊字符,例如:「!」和「^」。

所以我的問題是:我怎樣才能重新格式化這段代碼不拋出最大遞歸級別達到錯誤? (我意識到這個問題有多頻繁,這只是我的一半問題,請耐心等待)

其次,有人能解釋一下這段代碼如何在本地環境中起作用嗎?

SETLOCAL EnableDelayedExpansion 
FOR /R %%f IN (*.*) DO (
    ECHO !FILES_DONE!/!FILES_TOTAL! 
    ENDLOCAL & (
    SET "FILES_TEMP=%%f" 
) 
    [etc...] 
) 

例如,一旦它遍歷一次代碼,將在「ENDLOCAL」仍然在起作用,還是會被恢復,因爲它是一個新的循環?此外,它是否會有助於實現最大限定本地級別?

###########################################################################################

德爾2.0 - 完整文件內容對任何人想要使用它
注:如果有人想德爾批量的更新副本,給我發短信;它目前在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 

回答

3

保持Delayed Expansion使用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_DONEFILES_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

謝謝,我會立即測試,並接受它,如果它證明工作順利。當「:release」包含「exit/b」時,我可以使用「goto:release」來代替使用「goto:eof」。 「退出」會殺死腳本,而「退出/ b」會終止呼叫?對不起,我很不熟悉CALL – JoeBro

+0

@JoeBro請閱讀http://ss64.com/nt/goto.html中的** EOF **段落 - 「goto:eof」和「exit/B如果啓用[命令擴展](http://ss64.com/nt/cmd.html),則它們是等效的。請**不要**在腳本的任何位置聲明':eof'標籤以保持安全。 – JosefZ

+0

它完美的作品!我編輯提供的代碼,以便與腳本的其餘部分「玩得很開心」;但是,謝謝,只要我有其他的子問題回答,我會立即接受這個答案;但是解決了大部分問題。至少有人能爲我贊成這個嗎?是的,我記得:eof實際上表示文件的結尾而不是實際的標籤;謝謝你告訴我他們是相同的,這是非常有用的信息。 – JoeBro