Выход из цикла 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