
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 :EOF
y exit /b
ambos 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 words
se agregan.
Respuesta1
Simplemente coloque una etiqueta :nextiteration
(o cualquier otro nombre que desee) como última declaración dentro del cuerpo del bucle for y goto
en 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
call
para llamar a una rutina que contiene todo el bucle interno, dondeexit/B
funcionará:@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 :Label
y colóqueloLabel:
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