このバッチファイルがループから抜け出さないのはなぜですか?
For /L %%f In (1,1,1000000) Do @If Not Exist %%f Goto :EOF
Goto :EOF
ループから抜け出しますか?
もっと明示的に尋ねるべきだったと思います... howループから抜け出すことができますか?
Timの2番目の編集 および このページ に基づいて、これを行うことができます。
@echo off
if "%1"=="loop" (
for /l %%f in (1,1,1000000) do (
echo %%f
if exist %%f exit
)
goto :eof
)
cmd /v:on /q /d /c "%0 loop"
echo done
このページ はループ内でgotoを使用する方法を提案します。動作するようですが、大きなループでは時間がかかります。したがって、gotoが実行される前に内部的にループを終了します。
単にecho on
を使用すると、goto :eof
またはexit /b
でさえ期待どおりに動作しないことがわかります。
ループ内のコードは実行されなくなりましたが、ループはすべての数値に対して最後まで展開されます。
だからこそとても遅いのです。
FOR/Lループを終了する唯一の方法は、Wimmelのexsampleのようなexit
のバリアントのようですが、これはループの結果にアクセスするのに非常に高速でも便利でもありません。
これは10個の展開を示していますが、いずれも実行されません
echo on
for /l %%n in (1,1,10) do (
goto :eof
echo %%n
)
だからこれはちょっと古いことを理解していますが、多くのグーグルの後、私は満足している答えを見つけることができませんでしたので、反復をすぐに停止するFORループを壊すための独自のソリューションを考え出し、共有したいと思いましたそれ。
ループは別のファイルにある必要があり、CMDエラー処理のバグを悪用して、DIRのSTDOUTをSTDINにリダイレクトするときにループファイルのバッチ処理をすぐにクラッシュさせます。
MainFile.cmd
ECHO Simple test demonstrating loop breaking.
ECHO.
CMD /C %~dp0\LOOP.cmd
ECHO.
ECHO After LOOP
PAUSE
LOOP.cmd
FOR /L %%A IN (1,1,10) DO (
ECHO %%A
IF %%A EQU 3 DIR >&0 2>NUL )
)
実行すると、次の出力が生成されます。 %A = 3の場合、ループの反復と実行の両方が停止することがわかります。
:>MainFile.cmd
:>ECHO Simple test demonstrating loop breaking.
Simple test demonstrating loop breaking.
:>ECHO.
:>CMD /C Z:\LOOP.cmd
:>FOR /L %A IN (1 1 10) DO (
ECHO %A
IF %A EQU 3 DIR 1>&0 2>NUL
)
:>(
ECHO 1
IF 1 EQU 3 DIR 1>&0 2>NUL
)
1
:>(
ECHO 2
IF 2 EQU 3 DIR 1>&0 2>NUL
)
2
:>(
ECHO 3
IF 3 EQU 3 DIR 1>&0 2>NUL
)
3
:>ECHO.
:>ECHO After LOOP
After LOOP
:>PAUSE
Press any key to continue . . .
ループから単一の変数を保持する必要がある場合は、ループにその変数の結果をECHOさせ、MainFile.cmdでFOR/Fループを使用してLOOP.cmdファイルの出力を解析します。
例(上記と同じLOOP.cmdファイルを使用):
MainFile.cmd
@ECHO OFF
ECHO.
ECHO Simple test demonstrating loop breaking.
ECHO.
FOR /F "delims=" %%L IN ('CMD /C %~dp0\LOOP.cmd') DO SET VARIABLE=%%L
ECHO After LOOP
ECHO.
ECHO %VARIABLE%
ECHO.
PAUSE
出力:
:>MainFile.cmd
Simple test demonstrating loop breaking.
After LOOP
3
Press any key to continue . . .
複数の変数を保持する必要がある場合は、以下に示すように一時ファイルにリダイレクトする必要があります。
MainFile.cmd
@ECHO OFF
ECHO.
ECHO Simple test demonstrating loop breaking.
ECHO.
CMD /C %~dp0\LOOP.cmd
ECHO After LOOP
ECHO.
SET /P VARIABLE1=<%TEMP%\1
SET /P VARIABLE2=<%TEMP%\2
ECHO %VARIABLE1%
ECHO %VARIABLE2%
ECHO.
PAUSE
LOOP.cmd
@ECHO OFF
FOR /L %%A IN (1,1,10) DO (
IF %%A EQU 1 ECHO ONE >%TEMP%\1
IF %%A EQU 2 ECHO TWO >%TEMP%\2
IF %%A EQU 3 DIR >&0 2>NUL
)
出力:
:>MainFile.cmd
Simple test demonstrating loop breaking.
After LOOP
ONE
TWO
Press any key to continue . . .
他の人が、反復を継続するために終了するのに時間がかかりすぎるループを壊すのに役立つことを願っています。
OPがcmd.exeでバッチファイルを呼び出し、forループから適切に抜け出すために、ラベルに移動すると仮定します。
これを変える:
For /L %%f In (1,1,1000000) Do If Not Exist %%f Goto :EOF
これに:
For /L %%f In (1,1,1000000) Do If Not Exist %%f Goto:fileError
.. do something
.. then exit or do somethign else
:fileError
GOTO:EOF
さらに良いことに、エラー報告をいくつか追加します。
set filename=
For /L %%f In (1,1,1000000) Do(
set filename=%%f
If Not Exist %%f set tempGoto:fileError
)
.. do something
.. then exit or do somethign else
:fileError
echo file does not exist '%filename%'
GOTO:EOF
これはあまり知られていないcmd.exe/DOSバッチファイルの機能とトリックに関する役立つサイトであることがわかりました。 https://www.dostips.com/
これについて少し調べたところ、1から2147483647まで1ずつループしているようです。
(1、1、2147483647):最初の番号は開始番号、次の番号はステップ、最後の番号は終了番号です。
追加して編集
テスト条件に関係なく、ループは最後まで実行されるようです。テストした
FOR /L %%F IN (1, 1, 5) DO SET %%F=6
そして、それは非常に迅速に実行されました。
2番目の編集
これはバッチファイルの唯一の行であるため、EXITコマンドを試すことができます。
FOR /L %%F IN (1, 1, 2147483647) DO @IF NOT EXIST %%F EXIT
ただし、これにより、DOSプロンプトウィンドウも閉じられます。