FOR 루프에서 사이클을 건너뛰려면 어떻게 해야 합니까?

FOR 루프에서 사이클을 건너뛰려면 어떻게 해야 합니까?

일부 파일을 처리하기 위해 배치 스크립트를 실행하고 있습니다. 현재 파일에 처리가 필요하지 않다고 판단되면 해당 파일에 대한 나머지 명령을 건너뛰고 바로 다음 파일로 이동하고 싶습니다. 어떻게? Goto :EOFexit /b다 전체 스크립트를 종료합니다.

여기에 스크립트가 있습니다. 디렉터리를 가져와 파일 이름에 이미 포함된 단어를 제외하고 상위 디렉터리 이름의 모든 단어를 포함하도록 모든 파일의 이름을 바꿉니다.

@echo off
setlocal enabledelayedexpansion

rem set input directory (add check for validity)
set "inputDir=%~1"
set "confirmation=false"

:proceed
for /r "%inputDir%" %%F in (*.*) do (
    rem use path to file as keywords
    set "words=%%~pF"
    rem replace known useless marks with spaces
    set "words=!words:\= !"
    set "words=!words:_= !"
    set "words=!words:,= !"
    set "words=!words:  = !"
    rem remove known useless words
    set "words=!words: The = !"
    set "words=!words: A = !"
    set "words=!words: An = !"
    set "words=!words: Video = !"
    set "words=!words: New Folder = !"
    rem remove word that already exists in the filename
    for %%W in (!words!) do echo %%~nF | find /i "%%W" >nul && set "words=!words: %%W = !"
    rem replace leading and trailing spaces with brackets
    set "words=[!words:~1,-1!]"
    rem if all words already included end task for current file
    if "!words!"=="[]" exit /b
    rem build the new filename
    set "newName=%%~nF !words!%%~xF"
    rem fix "] [" caused by repeated renaming, causes fusion with non-related bracketed sets, which is fine
    set "newName=!newName:] [= !"
    rem task for displaying the name change for confirmation
    if /i not "%confirmation%"=="yes" echo old "%%F" && echo new "!newName!"
    rem task for doing the actual rename if confirmed
     if /i "%confirmation%"=="yes" echo ren "%%~nxF" "!newName!" & echo ren "%%F" "!newName!"
)

rem fails to rename files with ! mark in the filename. no other trouble, just won't rename those. error: the syntax of the command is incorrect

rem if coming from second (completed) run then exit
if /i "%confirmation%"=="yes" exit /b
rem ask for confirmation to run again for real
set /p confirmation="confirm you want to perform all these rename tasks (type yes or no)?: "
if /i not "%confirmation%"=="yes" echo confirmation denied
if /i "%confirmation%"=="yes" goto proceed

endlocal

또한 다음과 같이 마지막 명령을 조건부로 실행하는 대체 방법을 시도하고 있습니다.

@echo off
setlocal enabledelayedexpansion

rem set input directory (add check for validity)
set "inputDir=%~1"
set "confirmation=false"

:proceed
for /r "%inputDir%" %%F in (*.*) do (
    rem use path to file as keywords
    set "words=%%~pF"
    rem replace known useless marks with spaces
    set "words=!words:\= !"
    set "words=!words:_= !"
    set "words=!words:,= !"
    set "words=!words:  = !"
    rem remove known useless words
    set "words=!words: The = !"
    set "words=!words: A = !"
    set "words=!words: An = !"
    set "words=!words: Video = !"
    set "words=!words: New Folder = !"
    rem remove word that already exists in the filename
    for %%W in (!words!) do echo %%~nF | find /i "%%W" >nul && set "words=!words: %%W = !"
    rem replace leading and trailing spaces with brackets
    set "words=[!words:~1,-1!]"
    rem if all words not already included in the filename do
    if not "!words!"=="[]" (
        rem build the new filename
        set "newName=%%~nF !words!%%~xF"
        rem fix "] [" caused by repeated renaming, causes fusion with non-related bracketed sets, which is fine
        set "newName=!newName:] [= !"
        rem task for displaying the name change for confirmation
        if /i not "%confirmation%"=="yes" echo old "%%F" && echo new "!newName!"
        rem task for doing the actual rename if confirmed
        if /i "%confirmation%"=="yes" echo ren "%%~nxF" "!newName!" & echo ren "%%F" "!newName!"
    )
)

rem fails to rename files with ! mark in the filename. no other trouble, just won't rename those. error: the syntax of the command is incorrect

rem if coming from second (completed) run then exit
if /i "%confirmation%"=="yes" exit /b
rem ask for confirmation to run again for real
set /p confirmation="confirm you want to perform all these rename tasks (type yes or no)?: "
if /i not "%confirmation%"=="yes" echo confirmation denied
if /i "%confirmation%"=="yes" goto proceed

endlocal

그러나 이는 재앙으로, words추가된 파일 이름의 무작위 부분에서 파일 이름이 잘려지는 결과를 낳습니다.

답변1

for-loop 본문 내부의 마지막 문으로 레이블 :nextiteration(또는 원하는 다른 이름)을 배치하고 gotofor-body의 나머지 부분을 건너뛸 수 있다고 결정한 경우 해당 레이블에 배치하세요.

FOR 본문의 닫는 괄호 앞에는 일반 문(레이블은 해당되지 않음)이 와야 하기 때문에 레이블과 닫는 괄호 사이에 더미 문(예: REM)을 배치해야 합니다.

FOR xxxxxxxxx DO (
  some statements (executed on each iteration)
  IF {some condition is met} GOTO nextiteration
  statements that will be skipped if conditon is met
:nextiteration
  REM to prevent syntax error
)

답변2

Windows 배치에는 루프 반복을 건너뛰는 옵션이 너무 많지 않습니다. 사용할 수 있는 방법은 다음과 같습니다.

  • 건너뛰려는 루프 부분 주위에 IF 블록을 배치합니다.

    @Echo Off
    if A equ A (
      IF B==C (
        Echo shouldn't go here
      )
    )
    
  • call전체 내부 루프가 포함된 루틴을 호출하는 데 사용됩니다 exit/B. 여기서는 다음과 같이 작동합니다.

     @Echo Off
     Setlocal 
     For %%A in (alpha beta gamma) DO (
       Echo Outer loop %%A
       Call :inner 
     )
     Goto :eof
    
     :inner
     For %%B in (U V W X Y Z) DO (
       if %%B==X ( exit /b 2 )
       Echo    Inner loop    Outer=%%A Inner=%%B
     )
    
  • 명령을 사용 goto :Label하고 Label: 루프 끝에 넣으십시오. 알려진 버그로 인해 귀하의 경우에는 작동하지 않을 수 있습니다. FOR 및 IF 명령을 포함하여 괄호 안에 GOTO를 사용하면 오류가 발생합니다.
    버그를 보여주는 예:

    @Echo Off
    if A equ A (
      IF B==C GOTO specialcase 
        Echo shouldn't go here
        goto:eof 
    :specialcase
    )
    

참조 :

답변3

다음을 사용해 보세요 For /F....... | findstr /c:"string1" /c:"string2"...

문자열을 필터링할 수 있는 루프를 사용하면 결과 interrese 파일 이름으로 작업을 더 잘 제어할 수 있습니다. 이렇게 하면 루프가 더 정확해지기 때문에 루프를 건너뛰지 않고도 이름을 바꾸는 상호 작용을 더 쉽게 제공할 수 있습니다.

@echo off & setlocal

2>nul cd /d "%~1" || exit 

setlocal enabledelayedexpansion

for %%G in =;( 
     "_",",","  "," The "," A "," An "," Video "," New Folder " 
    );= do if not defined _str2find =;( set "_str2find=/c:"%%~G""
        );= else call set "_str2find=!_str2find! /c:"%%~G""

setlocal disabledelayedexpansion

for /f usebackq^delims^= %%G in (`
    2^>nul where /r . *.* ^| findstr %_str2find% `);= do =;( 
      echo/%%~G 
      :: So you don't need to use skip, the rest of your 
      :: interactions continue here and within your loop 
     );=

endlocal 

관련 정보