
Я запускаю пакетный скрипт для обработки некоторых файлов. Когда он определяет, что текущий файл не нуждается в обработке, я хотел бы пропустить остальные команды для этого файла и перейти сразу к следующему. Как? Goto :EOF
и exit /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
Просто поместите метку :nextiteration
(или любое другое имя, которое вам нравится) в качестве последнего оператора внутри тела цикла for и goto
используйте эту метку, когда решите, что можете пропустить остальную часть тела цикла for.
Поскольку закрывающей скобке в теле 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:
в конец цикла. Это, вероятно, не сработает в вашем случае из-за известной ошибки: использование GOTO в скобках, включая команды FOR и IF, сломает его.
Пример, демонстрирующий ошибку:@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