У меня есть 4 пакетных файла, которые я запускаю для файлов MKV. Первый переименовывает все файлы, второй удаляет все комментарии во всех файлах, третий редактирует «Заголовок» в метаданных, чтобы он соответствовал именам файлов, а четвертый создает каталог для каждого имени файла, а затем перемещает в них mkvs. Все 4 файла работают отлично, но я пытаюсь объединить их в один пакетный файл. Мне удалось это сделать, и это некрасиво, но работает. Проблема в том, что когда все файлы готовы и прошли все процессы, пакетный файл не завершается. Он продолжает перезапускаться снова и снова. Может кто-нибудь помочь?
Вот объединенный пакетный файл...
@ECHO OFF
@echo Renaming Files...
pause
SETLOCAL EnableExtensions DisableDelayedExpansion
set "mkv=C:\Users\Immortalis\Downloads\-=UT=-\! SAVED DOWNLOADS\mkvtoolnix\mkvpropedit.exe"
pushd "."
FOR /f "delims = " %%G IN ('dir /a-d /b /s /o-n') DO (
SET "_FFN=%%~fG" File Full Name
SET "Var=%%~nxG" File Name + Extension
call :renaming
)
popd
ENDLOCAL
goto :EOF
:renaming
SET "Var=%Var:(1 = {1%"
SET "Var=%Var:(2 = {2%"
SET "Var=%Var:0)=0}%"
SET "Var=%Var:1)=1}%"
SET "Var=%Var:2)=2}%"
SET "Var=%Var:3)=3}%"
SET "Var=%Var:4)=4}%"
SET "Var=%Var:5)=5}%"
SET "Var=%Var:6)=6}%"
SET "Var=%Var:7)=7}%"
SET "Var=%Var:8)=8}%"
SET "Var=%Var:9)=9}%"
SET "Var=%Var:(Ur)=(U)%"
SET "Var=%Var:(Unrated)=(U)%"
SET "Var=%Var:.trim01=%"
SET "Var=%Var:[DR]=[D]%"
SET "Var=%Var:[WR]=[W]%"
SET "Var=%Var:[HD]=[H]%"
SET "Var=%Var:[BR]=[B]%"
SET "Var=%Var:[s = {s%"
SET "Var=%Var:00]=00}%"
SET "Var=%Var:01]=01}%"
SET "Var=%Var:02]=02}%"
SET "Var=%Var:03]=03}%"
SET "Var=%Var:04]=04}%"
SET "Var=%Var:05]=05}%"
SET "Var=%Var:06]=06}%"
SET "Var=%Var:07]=07}%"
SET "Var=%Var:08]=08}%"
SET "Var=%Var:09]=09}%"
SET "Var=%Var:10]=10}%"
SET "Var=%Var:11]=11}%"
SET "Var=%Var:12]=12}%"
SET "Var=%Var:13]=13}%"
SET "Var=%Var:14]=14}%"
SET "Var=%Var:15]=15}%"
SET "Var=%Var:16]=16}%"
SET "Var=%Var:17]=17}%"
SET "Var=%Var:18]=18}%"
SET "Var=%Var:19]=19}%"
SET "Var=%Var:20]=20}%"
SET "Var=%Var:21]=21}%"
SET "Var=%Var:22]=22}%"
SET "Var=%Var:23]=23}%"
SET "Var=%Var:24]=24}%"
SET "Var=%Var:25]=25}%"
SET "Var=%Var:26]=26}%"
rename "%_FFN%" "%Var%"
@echo Removing Comments...
pause
for /R "." %%I in (*.mkv) do "%mkv%" "%%I" --tags all: -d title --delete-attachment 1
@echo Setting Title to filename...
pause
for /R "." %%I in (*.mkv) do "%mkv%" "%%I" --edit info --set title = "%%~nI"
@echo Placing files in separate directories...
pause
if not "%%~ni" == "organize" (
md "%%~ni" && move "%%~i" "%%~ni"
)
)
goto :EOF
:EOF
@echo Processes Complete!
pause
Спасибо за любую помощь.
Пятый пакетный файл имеет смысл... Попробую. Что касается того, насколько далеко он заходит, я уже упоминал, что он завершает все до конца, но затем начинает заново и продолжает зацикливаться.
На самом деле, единственное место, которое может вызвать рекурсию, — это call :renaming
. Похоже, он не выходит из этого цикла.
Пятое решение с пакетным файлом будет простым. Пятый файл можно было бы назвать примерно так: Cleanup.bat
. В нем будет четыре строки, каждая из которых будет содержать имя одного из четырех других, каждая на отдельной строке. Что-то вроде RenameFiles
, CleanComments
, ChangeTitles
, MoveTheFiles
.
После переименования он выходит из цикла и выполняет все остальные процессы, но затем возвращается к переименованию и проходит все процессы снова и снова.
Я попробовал идею с пятым пакетным файлом, и он не переименовал файл, поэтому отредактировал заголовок с неправильным именем, создал каталог с неправильным именем и переместил в него файл.
Тогда ваши четыре отдельных пакетных файла не могли работать идеально, не так ли?
Я не могу этого объяснить... но если запускать их по отдельности, они работают нормально. Делает именно то, что мне нужно.
Хорошо, у меня работает пятая идея пакетного файла. Проблема была связана с именем тестового файла. Как только я это исправил, пакетный файл переименовывает его правильно, десять завершает другие процессы.
Было бы удобнее хранить все это в одном файле, но все равно дела обстоят лучше, чем были. Спасибо всем за вашу помощь.
Я думаю, что эта строка неправильная или неполная: if not "%%~ni" == "organize" (
. Нет соответствующей предыдущей команды for %%i ...
Я не понимаю, что вы имеете в виду, но это из четвертого пакетного файла, который работает нормально, и у меня никогда не было с ним никаких проблем. Я не создавал ни одного из этих пакетных файлов, они были найдены в сети и изменены для собственного использования, поэтому, если что-то не так, я не знаю, что и как это исправить... вот почему Я здесь :)
В комментарии @Aacini не говорится, что это не сработает, он сказал, что это неправильно, т. е. он не будет обрабатывать это утверждение if
. Вы никогда не ставили %%i
только %%I
Если :renaming
подразумевает подпрограмму, то exit /b
отсутствует. Пример синтаксиса смотрите здесь. Кроме того, убедитесь, что «поток» не попадает в вашу подпрограмму — этого можно добиться с помощью goto
, который ставится перед меткой.
В вашем четвертом пакетном файле перед строкой if not "%%~ni" == "organize" (
должна быть строка for %%i ...
, которую вы пропустили в объединенном пакетном файле. Проверьте это! В любом случае, вся ваша логика неверна. Смотрите мой ответ ниже...
В общем, если вы хотите объединить 4 пакетных файла, вы можете использовать эту структуру (предположим, у вас есть PartOne.cmd, PartTwo.cmd, PartThree.cmd и PartFour.cmd):
AllParts.cmd:
@echo off
SETLOCAL EnableExtensions DisableDelayedExpansion
echo Start processing...
REM Here is a good place for parameters used by all parts
REM Store them in environment variables to be used across
REM the parts
call :PartOne
call :PartTwo
call :PartThree
call :PartFour
goto :Done
:PartOne
REM ... your code of PartOne.cmd ...
exit /b
:PartTwo
REM ... your code of PartTwo.cmd ...
exit /b
:PartThree
REM ... your code of PartThree.cmd ...
exit /b
:PartFour
REM ... your code of PartFour.cmd ...
exit /b
:Done
ENDLOCAL
ECHO Processing done!
Скопируйте части ваших cmd-файлов в этот один файл и протестируйте его.
Примечание:
exit /b
гарантирует, что код продолжится со строки, следующей за оператором call
. Простое использование exit
приведет к завершению командного файла (что вам не нужно).call
важно использовать двоеточие (:
), без него call
будет искать доступную по пути внешнюю команду и выполнять ее, например call calc.exe
откроет калькулятор Windows.Это прекрасно работает!!! Большое спасибо!!
Каждый из четырех исходных пакетных файлов обрабатывает все файлы *.mkv. В объединенном пакетном файле для каждого файла .mkv, который исходный первый пакетный файл обрабатывает с помощью команды FOR /f "delims = " %%G IN ('dir /a-d /b /s /o-n') DO (
, вы вызываете остальные три файла! Это означает, что 2-й, 3-й и 4-й пакетные файлы вызываются много раз!
Я ДУМАЮ, что ваш объединенный командный файл должен выглядеть так:
@ECHO OFF
@echo Renaming Files...
pause
SETLOCAL EnableExtensions DisableDelayedExpansion
set "mkv=C:\Users\Immortalis\Downloads\-=UT=-\! SAVED DOWNLOADS\mkvtoolnix\mkvpropedit.exe"
REM pushd "." <- this command is not useful
FOR /f "delims = " %%G IN ('dir /a-d /b /s /o-n') DO (
SET "_FFN=%%~fG" & REM File Full Name
SET "Var=%%~nxG" & REM File Name + Extension
call :renaming
)
REM popd <- the same
@echo Removing Comments...
pause
for /R "." %%I in (*.mkv) do "%mkv%" "%%I" --tags all: -d title --delete-attachment 1
@echo Setting Title to filename...
pause
for /R "." %%I in (*.mkv) do "%mkv%" "%%I" --edit info --set title = "%%~nI"
@echo Placing files in separate directories...
pause
FOR something %%i ... ( <- this command was missed from the original 4th batch file!
if not "%%~ni" == "organize" (
md "%%~ni" && move "%%~i" "%%~ni"
)
)
@echo Processes Complete!
pause
ENDLOCAL
goto :EOF
:renaming
SET "Var=%Var:(1 = {1%"
SET "Var=%Var:(2 = {2%"
SET "Var=%Var:0)=0}%"
. . . the rest of renaming lines
SET "Var=%Var:25]=25}%"
SET "Var=%Var:26]=26}%"
rename "%_FFN%" "%Var%"
goto :EOF
Возможно, вы также захотите сократить подпрограмму :renaming
следующим образом:
:renaming
setlocal EnableDelayedExpansion
for %%i in (1 2) SET "Var=!Var:(%%i = {%%i!"
for /L %%i in (0,1,9) do SET "Var=!Var:%%i)=%%i}!" & SET "Var=!Var:0%%i]=0%%i}!"
for %%a in ("(Ur)=(U)" "(Unrated)=(U)" ".trim01 = " "[DR]=[D]" "[WR]=[W]" "[HD]=[H]" "[BR]=[B]" "[s = {s" do (
SET "Var=!Var:%%~a!"
)
for /L %%i in (10,1,26) do SET "Var=!Var:%%i]=%%i}!"
rename "!_FFN!" "!Var!"
goto :EOF
PS. Не следует определять ярлык :EOF
. Такая метка игнорируется. Команда goto :EOF
всегда завершает командный файл или подпрограмму...
Как уже упоминалось... где-то в одном из комментариев я не создавал эти скрипты, я нашел их в сети и модифицировал для собственного использования. Вещи, которые неправильны, отсутствуют или не имеют значения, выше моего понимания. Все они работали нормально, я просто хотел упростить задачу, объединив их в один пакетный файл, что, к счастью, сделал Мэтт.
Проблема решена. Спасибо всем за ваши усилия и идеи. Даже на тех, которые я не использовал или не работал, я учился у них и очень ценю это!
Почему бы вам просто не создать пятый пакетный файл, который ничего не делает, а вызывает остальные четыре: это было бы намного проще, и вы все равно запускали бы только один файл. Кроме того, вам нужно будет быть более конкретным. Насколько далеко зашел процесс, прежде чем возникнет проблема? Вы выводите информацию о состоянии на терминал, поэтому у вас должна быть возможность сузить область кода, в которой возникают проблемы. Я не вижу ничего очевидного, что заставило бы его рекурсивно вызывать себя. Пробовали ли вы закомментировать части кода, чтобы иметь возможность его отследить?