Выход из цикла FOR в пакетном файле?
Почему этот пакетный файл никогда не выходит из цикла?
For /L %%f In (1,1,1000000) Do @If Not Exist %%f Goto :EOF
Не следует ли выйти из цикла Goto :EOF
?
Edit:
Я думаю, мне следовало бы более подробно рассказать... как я могу вырваться из цикла?
Ответы
Ответ 1
На основе Tim second edit и эта страница вы можете сделать это:
@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.
Ответ 2
Вы можете просто использовать echo on
, и вы увидите, что goto :eof
или даже exit /b
не работает должным образом.
Код внутри цикла больше не выполняется, но цикл расширяется для всех номеров до конца.
Вот почему это так медленно.
Единственным способом выхода из цикла FOR/L является вариант exit
, такой как exsample для Wimmel, но это не очень быстро и полезно для доступа к каким-либо результатам из цикла.
Это показывает 10 расширений, но ни один из них не будет выполнен
echo on
for /l %%n in (1,1,10) do (
goto :eof
echo %%n
)
Ответ 3
Как jeb отметил, остальная часть цикла пропускается , но оценивается, что делает решение FOR
слишком медленным для этой цели. Альтернатива:
set F=1
:nextpart
if not exist "%F%" goto :EOF
echo %F%
set /a F=%F%+1
goto nextpart
Возможно, вам придется использовать задержанное расширение и call
подпрограммы при использовании этого в циклах.
Ответ 4
Итак, я понимаю, что это уже давно, но после многого разговора я не смог найти ответ, которым я был доволен, поэтому я придумал свое собственное решение для взлома цикла FOR, которое немедленно останавливает итерацию, и подумал, что я 'd поделиться им.
Он требует, чтобы цикл находился в отдельном файле и использовал ошибку в обработке ошибок CMD, чтобы немедленно сбой пакетной обработки файла цикла при перенаправлении STDOUT DIR в 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 в результате переменной и используйте цикл FOR/F в MainFile.cmd для анализа вывода файла 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 . . .
Я надеюсь, что другие находят это полезным для прерывания циклов, которые в противном случае слишком долго выходили бы из-за продолжения итерации.
Ответ 5
Немного исследовал это, кажется, что вы выполняете цикл от 1 до 2147483647 с шагом в 1.
(1, 1, 2147483647): первым номером является начальный номер, следующим числом является шаг, а последний номер - конечный номер.
Отредактировано для добавления
Похоже, что цикл работает до завершения независимо от условий тестирования. Я тестировал
FOR /L %%F IN (1, 1, 5) DO SET %%F=6
И он работал очень быстро.
Второе редактирование
Так как это единственная строка в пакетном файле, вы можете попробовать команду EXIT:
FOR /L %%F IN (1, 1, 2147483647) DO @IF NOT EXIST %%F EXIT
Однако это также закроет окно подсказки DOS.
Ответ 6
Предполагая, что 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/
Ответ 7
вам не нужен отдельный командный файл для выхода из цикла с использованием exit/b, если вы используете call вместо goto наподобие
call :loop
echo loop finished
goto :eof
:loop
FOR /L %%I IN (1,1,10) DO (
echo %%I
IF %%I==5 exit /b
)
в этом случае "exit/b" выйдет из "вызова" и продолжит со строки после "вызова"
Итак, вывод такой:
1
2
3
4
5
loop finished