¿Cómo puedo saltarme un ciclo en un bucle FOR?

¿Cómo puedo saltarme un ciclo en un bucle FOR?

Estoy ejecutando un script por lotes para procesar algunos archivos. Cuando determina que el archivo actual no necesita procesamiento, me gustaría omitir el resto de los comandos para ese archivo y pasar directamente al siguiente. ¿Cómo? Goto :EOFy exit /bambos salen del script completo.

Aquí está el guión. Toma un directorio y cambia el nombre de todos los archivos para incluir todas las palabras de los nombres del directorio principal, excepto las que ya están incluidas en el nombre del archivo.

@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

También estoy probando un método alternativo para ejecutar condicionalmente los últimos comandos como este

@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

Pero esto es un desastre, ya que da como resultado nombres de archivos que se cortan de partes aparentemente aleatorias del nombre del archivo y wordsse agregan.

Respuesta1

Simplemente coloque una etiqueta :nextiteration(o cualquier otro nombre que desee) como última declaración dentro del cuerpo del bucle for y gotoen esa etiqueta cuando decida que puede omitir el resto del cuerpo for.

Debido a que un paréntesis de cierre en un cuerpo FOR tiene que estar precedido por una declaración regular (una etiqueta no sirve), tendrá que colocar una declaración ficticia (como un REM) entre la etiqueta y el paréntesis de cierre.

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
)

Respuesta2

El lote de Windows no tiene demasiadas opciones para omitir una iteración del bucle. Los métodos que puedes utilizar son:

  • Coloque un bloque IF alrededor de la parte del bucle que desea omitir:

    @Echo Off
    if A equ A (
      IF B==C (
        Echo shouldn't go here
      )
    )
    
  • Úselo callpara llamar a una rutina que contiene todo el bucle interno, donde exit/Bfuncionará:

     @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
     )
    
  • Utilice el comando goto :Labely colóquelo Label: al final del bucle. Probablemente esto no funcione en su caso debido a un error conocido: el uso de GOTO entre paréntesis, incluidos los comandos FOR e IF, lo romperá.
    Un ejemplo que muestra el error:

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

Referencia :

Respuesta3

Intenta usar For /F...y... | findstr /c:"string1" /c:"string2"...

Utilice un bucle que le permita filtrar las cadenas y así dar más control sobre las acciones con los nombres de archivos interrese resultantes, esto hace que sea más fácil darle interacciones para cambiarles el nombre sin intentar saltarse el bucle a medida que se vuelve más preciso:

@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 

información relacionada