2016-06-11 4 views
3

私は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!はすべての整数VARSあります。

!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

次のようにcall commandを使用して無効Delayed Expansionしてください:

@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コマンドは、変数を更新するために2回使用されていることに注意してください(見ることができる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

おかげで、私はすぐにそれをテストし、それが滞りなく作業が判明した場合、それを受け入れるだろう。 "goto:eof"を使用する代わりに、 ":release"に "exit/b"が含まれている場合、 "goto:release"を使用できますか? "exit"はスクリプトを殺し、 "exit/b"は呼び出しを終了させるでしょうか? eof'と '終了/ B:'後藤を - むしろ基本質問については申し訳ありませんが、私はhttp://ss64.com/nt/goto.htmlにCALL – JoeBro

+0

@JoeBro読みください** EOF **段落に非常に慣れていませんよ'は、[Command Extensions](http://ss64.com/nt/cmd.html)が有効な場合、同等です。 **あなたのスクリプトのどこにでも ':eof'ラベルを宣言しておかないでください。 – JosefZ

+0

これは完璧に動作します!私は提供されたコードをスクリプトの残りの部分と "うまくやる"ように編集しました。しかし、ありがとう、私は答えとして他のサブ質問に答えるとすぐにこれを受け入れます。それは問題の大半を解決します。誰かが少なくとも私のためにこれをupvoteできますか?ええ、私は覚えています:eofは実際に実際のラベルの代わりにファイルの終わりを意味します。私にそれらが同等であることを知らせてくれてありがとう、それは非常に有用な情報です。 – JoeBro

関連する問題