Как разделить имя файла по разделителю "-" и повторить часть до и после - PullRequest
0 голосов
/ 04 марта 2019

Мне нужна помощь, чтобы разделить имя файла или имя папки на 2 части.Все файлы в подпапках используют всегда одно и то же соглашение об именах: (основная папка / Artist - заголовок / Artist - заголовок .ext).

Я начинаю создавать пакет, который пишетФайлы .nfo (рекурсивные) для видеофайлов.Все работает нормально, я просто не могу найти способ отобразить part1 (artist) до delimeter = - и после него part2 (title) .

Вот что у меня сейчас:

@echo off
TITLE NFO creator Musicvideos
COLOR B
ECHO -------------------------------------------------------------------------
ECHO  Create NFO for Musicvideos, all existing will be overwritten
ECHO  Push key to Start
ECHO -------------------------------------------------------------------------
ECHO.
PAUSE > NUL
REM Ende Header
for /r %%a in (*.mkv *.avi *.mp4) do (
(
echo ^<?xml version="1.0" encoding="UTF-8" standalone="yes"?^>
echo ^<musicvideo^>
for %%b in ("%%~na") do echo ^  ^<title^>%%~b^</title^>
echo ^  ^<^!-- start test set attributes --^>
for %%b in ("%%~na") do echo ^  ^<path^>%~dp0^</path^>
for %%b in ("%%~na") do echo ^  ^<name^>%%~na^</name^>
for %%b in ("%%~na") do echo ^  ^<filenameandpath^>%%~a^</filenameandpath^>
for %%b in ("%%~na") do echo ^  ^<basepath^>%%~a^</basepath^>
for %%b in ("%%~na") do echo ^  ^<before^>^</before^>
REM for "tokens=1,2 delims= - " %%b  in ("%%~na") do (
REM echo ^  ^<before^>^%%a</before^>
REM echo ^  ^<after^>^%%b</after^>
REM )
REM test end
echo ^  ^<rating^>^0.000000^</rating^>
echo ^  ^<userrating^>^8^</userrating^>
echo ^  ^<epbookmark^>^0.000000^</epbookmark^>
echo ^  ^<year^>^</year^>
echo ^  ^<track^>^-1^</track^>
echo ^  ^<album^>^</album^>
echo ^  ^<artist^>^</artist^>
echo ^  ^<genre^>^</genre^> 
echo ^  ^<outline^>^</outline^>
echo ^  ^<plot^>^</plot^>
echo ^  ^<tagline^>^</tagline^>
echo ^  ^<thumb^>^</thumb^>
echo ^  ^<status^>^</status^>
echo ^  ^<studio^>^</studio^>
echo ^  ^<art^>
echo ^      ^<fanart^>%~dp0^%%~na^-fanart.jpg^</fanart^>
echo ^      ^<poster^>%~dp0^%%~na^-poster.jpg^</poster^>
echo ^      ^<artistthumb^>%~dp0^%%~na^-artistthumb.jpg^</artistthumb^>
echo ^      ^<banner^>%~dp0^%%~na^-banner.jpg^</banner^>
echo ^      ^<clearlogo^>%~dp0^%%~na^-clearlogo.png^</clearlogo^>
echo ^      ^<discart^>%~dp0^%%~na^-discart.png^</discart^>
echo ^      ^<landscape^>%~dp0^%%~na^-landscape.jpg^</landscape^>
echo ^  ^</art^>
echo ^</musicvideo^>
)>"%%~dpna.nfo"
)
ECHO.
ECHO Creatin is done
ECHO Push key to exit
ECHO.
PAUSE > NUL

Ответы [ 4 ]

0 голосов
/ 04 марта 2019

Вот как я бы это сделал:

@echo off
setlocal
for /R %%A in (*.mkv *.avi *.mp4) do call :SplitFileName "%%~nA"
goto :EOF

:SplitFileName
set "FileName=%~1"
set "Title=%FileName: - =" & set "Artist=%"
echo Artist=%Artist%
echo Title=%Title%
exit /B

Более подробная информация в Разделить строку со строкой в ​​качестве разделителя .Обратите внимание на комментарий при таком ответе ...

0 голосов
/ 04 марта 2019

Я не могу найти причину для всех циклов for %%b in ("%%~na") do, которые вы используете, особенно потому, что вы часто даже не используете %%b в своих телах.

В любом случае, разбиение имен файлов на определенном подэлементестроку можно легко сделать, сначала заменив подстроку одним символом, который запрещен в именах файлов (например, :), а затем используя этот символ в качестве разделителя в цикле for /F:

@echo off
setlocal EnableExtensions DisableDelayedExpansion

rem // Loop through all matching files recursively:
for /R %%a in (*.mkv *.avi *.mp4) do (
    rem // Store file name in variable:
    set "NAME=%%~na"
    rem /* Toggle delayed expansion to be able to write a variable
    rem    in the same block of code without losing `!`: */
    setlocal EnableDelayedExpansion
    rem // Remove everything before first occurrence of and including ` - `:
    echo Title:  !NAME:* - =!
    rem // Replace ` - ` by `:` and use the latter as delimiter:
    for /F "tokens=1 delims=: eol=:" %%b in ("!NAME: - =:!") do (
        endlocal
        echo Artist: %%b
    )
)

endlocal
exit /B

Приведенный выше код предполагает, что как исполнитель, так и заголовок не пусты.Часть заголовка может включать в себя подстроку - самостоятельно.

0 голосов
/ 04 марта 2019

При условии, что в вашем названии всегда есть только один - исполнитель, разделяющий название:

@echo off
setlocal enabledelayedexpansion

for /r %%a in (*.mkv *.avi *.mp4) do (
    set "fname=%%~na"
    set "fname=!fname: - =-!"
    for /f "tokens=1,2 delims=-" %%i in ("!fname!") do (
       echo The artist is %%i
       echo The title is %%j
       echo The extension is %%~xa
    )
)

Мы заменим space-space на -, а затем разделим его.

0 голосов
/ 04 марта 2019

Это пример того, как разделить имя файла на первый символ дефиса.

@echo off
setlocal EnableExtensions DisableDelayedExpansion
for /R %%A in (*.mkv *.avi *.mp4) do (
    for /F "eol=| tokens=1* delims=-" %%B in ("%%~nA") do (
        set "Artist=%%B"
        set "Title=%%C"
        setlocal EnableDelayedExpansion
        if "!Artist:~-1!" == " " set "Artist=!Artist:~0,-1!"
        if defined Title if "!Title:~0,1!" == " " set "Title=!Title:~1!"
        echo Artist=!Artist!
        if defined Title (echo Title=!Title!) else echo %%~na has no title.
        endlocal
    )
)
endlocal

Внешний цикл FOR ищет рекурсивный поиск в текущем каталоге и во всех подкаталогах для скрытогофайлы с расширением mkv, avi или mp4 и присваивает полное имя файла (путь к файлу + имя файла + расширение файла) найденного файла переменной цикла A.

Внутренний цикл FOR интерпретирует только имя файла без пути и расширение файла как строку для обработки.

Символ конца строки переопределяется по умолчанию ;, который может находиться в начале файлаимя |, которое никогда не может содержать имя файла, чтобы избежать случайного имени файла, начинающегося с точки с запятой, внутренним циклом FOR .

По умолчанию FOR с опцией /F обработка строки в двойных кавычках разбивает строку на подстроки с использованием обычного пробела и горизонтальной табуляции в качестве разделителей строк и назначает только первый пробел / разделитель табуляцииНоминальная строка для указанной переменной цикла.Это поведение разделения строк изменяется с помощью tokens=1* delims=- для разделения строки имени файла на дефисы вместо пробелов / табуляций с игнорированием дефисов в начале имени файла и назначением строки до первого дефиса внутри имени файла для указанной переменной цикла Bи все после первого (последовательности) дефиса (ов) до следующей переменной цикла в соответствии с ASCII таблицей без дальнейшего разделения строки, которое является переменной цикла C.

Другими словами наимя файла, например Artist - title, строка Artist с пробелом в конце присваивается переменной цикла B, а строка title с пробелом в начале присваивается переменной цикла C.Два нежелательных пространства должны быть удалены.Это можно сделать с помощью подстановки строк.Но это должно быть сделано с использованием отложенное расширение , которое еще не включено, поскольку имена файлов, содержащие восклицательный знак, также должны обрабатываться правильно.По этой причине отложенное расширение переменной среды затем включается во внутреннем цикле FOR .

Первое условие IF проверяет, является ли последний символ строки Artist действительно пробеломи выполняет подстановку строки для удаления этого пробела в конце строки исполнителя, если это условие истинно.

Второе условие IF сначала проверяет, определена ли переменная среды Title, потому что она вообще определена, потому чтокоманд внутреннего цикла FOR также выполняются для имени файла, вообще не содержит дефис, в этом случае %%C раскрывается в пустую строку, поэтому переменная окружения Title удаляется из списка окруженияпеременные.

Вложенное третье условие IF проверяет, является ли первый символ значения определенной переменной среды Title пробелом, и выполняет подстановку строки, чтобы переопределить Title без первого символа, если этоусловие истинно.

Теперь строки артиста и заголовка могут быть выведены перед delрасширение ayed снова отключается путем восстановления предыдущей среды.Пожалуйста, прочитайте этот ответ для подробностей о командах SETLOCAL и ENDLOCAL и что именно происходит при каждом выполнении SETLOCAL и ENDLOCAL из-за гораздо большего, чем просто включение и отключение отложенного расширения переменной среды для каждого найденного имени файла.

Примечание: Часть заголовка может содержать также пространство последовательности символов,дефис, пробел, а также один или несколько дефисов, но, конечно, строка исполнителя не должна содержать дефис, поскольку этот символ интерпретируется как разделитель между исполнителем и названием независимо от пробелов, существующих вокруг дефиса или нет.Процессор команды Windows не предназначен для расширенных манипуляций со строками, как другие интерпретаторы сценариев.Другой код будет необходим, если условием для разделения имени файла по исполнителю и заголовку должны быть пробел, дефис, пробел, а не просто дефис.

Другой код пакетного файла, использующий - для разделения имени файла на строки исполнителя и заголовка:

@echo off
setlocal EnableExtensions DisableDelayedExpansion
for /R %%A in (*.mkv *.avi *.mp4) do call :ProcessFileName "%%~nA"
endlocal
goto :EOF

:ProcessFileName
set "FileName=%~1"
set "Title=%FileName:* - =%"
setlocal EnableDelayedExpansion
set "Artist=!FileName: - %Title%=!"
echo Artist=!Artist!
echo Title=!Title!
endlocal
goto :EOF

Но это решение, использующее только подстановки строк в подпрограмме, не работает с строкой заголовка, содержащей знак равенстваиспользуется в качестве разделителя при подстановке строк.Это также намного медленнее по сравнению с вышеупомянутым решением для пакетных файлов при обработке большого количества имен файлов.

Для понимания используемых команд и их работы откройте окно командной строки, выполните там следующие команды иочень внимательно прочитайте все справочные страницы, отображаемые для каждой команды.

  • call /?
  • echo /?
  • endlocal /?
  • for /?
  • goto /?
  • if /?
  • set /?
  • setlocal /?

См. Также Куда возвращается GOTO: EOF?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...