Переименование папок путем разбора XML-файлов в папках - PullRequest
0 голосов
/ 05 мая 2019

Я хотел бы сократить файлы XML в папке и переименовать папку на основе тегов в файлах XML

E:\Test\Folder1\meta.xml
E:\Test\Folder2\meta.xml
E:\Test\Folder3\meta.xml

Содержимое файла meta.xml

<Title>XYZ</Title>
<Country>US</Country>
<Year>2014</Year>

Анализ XMLфайлы в папке и переименуйте их со значениями из трех узлов

Я пробовал несколько методов, но у меня есть проблемы с конечными слешами в конце

@ECHO OFF
SETLOCAL enableExtensions enableDelayedExpansion

SET "sourcedir=E:\Test\"

FOR /f "delims=" %%i IN ('findstr /s /m /L /c:"<Country>US</Country>" "%sourcedir%\*meta.xml"') DO (

REN "%%~dpi" "%%~dpi [US]"

)

я уверен, что это не таклучший метод, я пробовал несколько методов, но у меня есть проблемы с конечными слэшами

Я ожидаю, что выход Soruce:

E:\Test\Folder1
E:\Test\Folder2
E:\Test\Folder3

будет:

E:\Test\Folder1 (2005) [US]
E:\Test\Folder2 (2004) [US]
E:\Test\Folder3 (2002) [US]

Переименование папок по фразам лет и стран из соответствующего XML-файла в этих папках

Ответы [ 3 ]

1 голос
/ 05 мая 2019

Я предлагаю следующий пакетный файл для этой задачи:

@echo off
setlocal EnableExtensions DisableDelayedExpansion
set "SourceDir=E:\Test"
for /F "eol=| delims=" %%I in ('dir "%SourceDir%\meta.xml" /A-D /B /S 2^>nul') do (
    set "Country="
    set "Year="
    for /F "tokens=1,2 delims=< > " %%A in ('%SystemRoot%\System32\findstr.exe /R "<Country>[^<][^<]*</Country> <Year>[^<][^<]*</Year>" "%%I"') do (
        if "%%A" == "Country" if not defined Country set "Country=%%B"
        if "%%A" == "Year" if not defined Year set "Year=%%B"
    )
    if defined Country if defined Year (
        set "FilePath=%%~dpI"
        setlocal EnableDelayedExpansion
        echo !FilePath:~0,-1!| %SystemRoot%\System32\findstr.exe /E /I /L /C:" (!Year!) [!Country!]" >nul
        for %%J in ("!FilePath:~0,-1!") do if not exist "%%~J (!Year!) [!Country!]" ren "%%~J" "%%~nxJ (!Year!) [!Country!]"
        endlocal
    )
)
endlocal

ВНИМАНИЕ: Разделителями второго FOR являются левая угловая скобка <, символ горизонтальной табуляции, правая угловая скобка > и символ обычного пробела. Поэтому убедитесь, что эти четыре символа находятся в пакетном файле после копирования и вставки кода из окна браузера.

Переменная среды SourceDir определяется с путем к каталогу без обратной косой черты в конце, поскольку она объединяется с \meta.xml в следующей строке. Синтаксически было бы неправильно на 100% определять эту переменную с помощью E:\Test, так как это приводит к строке имени файла E:\Test\\meta.xml, содержащей два обратного слеша вместо одного между путем к файлу и именем файла.

Для каждого файла meta.xml, найденного командой DIR в исходном каталоге или любом из его подкаталогов, команда FOR выполняет исполняемый файл FINDSTR , который ищет регистр чувствителен (теги XML чувствительны к регистру) для элементов страны ИЛИ год со строковым значением не менее одного символа. Символ пробела в регулярном выражении поиска интерпретируется FINDSTR как ИЛИ , что не очень хорошо задокументировано.

Если переменные окружения Country и Year определены после поиска строк страны и года в meta.xml, путь к файлу текущего XML-файла назначается переменной окружения FilePath, которая всегда заканчивается обратной косой чертой .

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

Полное имя папки с путем выводится с ECHO и перенаправляется для обработки STDIN из FINDSTR , чтобы проверить, заканчивается ли имя папки (( правильный) год в круглых скобках и (правильный) страна в квадратных скобках. Этот дополнительный тест основан на коде, написанном LotPings .

Третий FOR выполняется только в том случае, если имя папки еще не заканчивается (правильным) годом, а страна используется для получения из пути к файлу без обратной косой черты в конце последнего имени папки, на которое ссылается %%~nxJ, что ссылается на строку после последней обратной косой черты независимо, если эта строка представляет собой имя файла с расширением или именем папки. %%~J указывает на имя текущей папки с полным путем без обратной косой черты в конце.

Примечание 1: Пакетный файл не предназначен для выполнения с исходным каталогом, являющимся корневым каталогом диска.

Примечание 2: Код не удаляет неправильный год / страну из имени папки, если файл meta.xml теперь содержит другой год или страну. Таким образом, папка с именем Folder1 (2015) [US] не переименовывается в Folder1 (2019) [India], если meta.xml в папке Folder1 (2015) [US] содержит теперь <Country>India</Country> и <Year>2019</Year>.

Примечание 3: Разбор строки, выполненный FOR , не работает, если файл XML содержит несколько элементов XML в одной строке. Элементы Country и Year должны находиться в отдельных строках без других элементов XML. Поэтому этот пакетный код нельзя использовать, если meta.xml содержит, например, <Country>India</Country><Year>2019</Year> в одной строке. Командный процессор Windows не имеет функций для анализа содержимого XML в XML-формате, как это поддерживает PowerShell.

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

  • dir /?
  • echo /?
  • endlocal /?
  • findstr /?
  • for /?
  • if /?
  • ren /?
  • set /?
  • setlocal /?
1 голос
/ 05 мая 2019
  • Я бы использовал for /d для итерации подпапок и проверки, существует ли файл meta.xml
  • при разборе xml используйте теги в качестве имен переменных для хранения значений.

:: Q:\Test\2019\05\05\SO_55992361.cmd
@ECHO Off
SET "sourcedir=E:\Test\"
PushD "%Sourcedir%" ||(Echo can't locate %sourcedir% & pause & Exit /B 1)
For /D %%F in (Folder*) Do if exist "%%~fF\meta.xml" call :sub "%%~fF\meta.xml" "%%~fF"
PopD
Goto :Eof

:Sub
Set "Country="
Set "Year="
for /f "tokens=1-2delims=<>" %%A in ('findstr /i "country year" %1') Do set "%%A=%%B"
Echo %~2|findstr /EIC:" (%Year%) [%country%]">Nul 2>&1 && Goto :Eof
if defined Country if defined Year (
Echo Ren "%~2" "%~n2 (%Year%) [%country%]"
     Ren "%~2" "%~n2 (%Year%) [%country%]"
)

Пример вывода:

> Q:\Test\2019\05\05\SO_55992361.cmd
Ren "E:\Test\Folder1" "Folder1 (2005) [US]"
Ren "E:\Test\Folder2" "Folder2 (2004) [US]"
Ren "E:\Test\Folder3" "Folder3 (2002) [US]"

РЕДАКТИРОВАТЬ: изменение партии из-за подсказок @ Mofi s. И успешно протестирован на FAT32

0 голосов
/ 05 мая 2019
@ECHO OFF
SETLOCAL
SET "sourcedir=U:\sourcedir"
SET "searchregex=<Country>.*</Country>"

FOR /f "delims=" %%i IN ('findstr /s /m /R "%searchregex%" "%sourcedir%\*meta.xml"') DO (
 rem here, %%i contains the name of the xml file.
 rem detect whether the subdirectory name ends with (year) [country]
 ECHO %%~dpi|FINDSTR /R ".*(.*) \[.*\]\\" >nul
 IF ERRORLEVEL 1 (rem no (year) [country] pattern found
  rem search that particular xml file for the Country tag and select the country to %%c
  FOR /f "tokens=2delims=<>" %%c IN ('findstr /R "%searchregex%" "%%i"') DO (
   rem repeat the search of the xml file for the Year tag and select the year to %%y
   FOR /f "tokens=2delims=<>" %%y IN ('findstr /R "%searchregex:Country=Year%" "%%i"') DO (
    rem now rename - note that a rename target may only be the NAME(extension)
    FOR /f "delims=" %%b IN ("%%~dpi.") DO ECHO REN "%%~fb" "%%~nxb (%%y) [%%c]"
   )
  )
 )
)

GOTO :EOF

Ну, это было интересно. Я добавил несколько вещей, чтобы соответствовать моему пониманию вашей цели.

Во-первых, я настроил регулярное выражение searchregex, потому что эта строка собиралась использоваться несколько раз, и я не мог ее исправить в нескольких местах.

Сначала выполните поиск файлов meta.xml. Если файл meta.xml содержится в каталоге, оканчивающемся на (year) [country], то я полагаю, что вы не хотите переименовывать в этот каталог , в противном случае вы получите E:\Test\Folder1 (2005) [US], превратившийся в E:\Test\Folder1 (2005) [US] (2005) [US] SO, если drive:path соответствует регулярному выражению {anystring}({anystring}) [{anystring}]\, тогда вы не хотите его обрабатывать, а errorlevel имеет значение 0. Примечание. В целях безопасности, возможно, добавьте переключатель /E к findstr, чтобы шаблон соответствовал только на внешнем листе.)

С теми, которые требуют переименования, найдите конкретный файл meta.xml (я предполагаю, что вам нужны любые имена файлов, оканчивающиеся на meta.xml) для тега country, используя searchregex, а затем снова найдите тот же файл, на этот раз заменив Country в поиске по Year, который я выполнил, используя подстановку строк, потому что это казалось подходящим в то время.

Если мы достигнем внутренней команды, то мы можем удалить терминал \ из строки пути, добавив ., а затем разрешив его, используя for/f в строке констант с delims= для преодоления токенизации.

И, наконец, создайте команду REN и ECHO, чтобы подпрограмма могла быть протестирована.

Удаление echo из echo ren включит функцию переименования.


@ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION 
SET "sourcedir=U:\sourcedir"
SET "searchregex=<Country>.*</Country>"

FOR /f "delims=" %%i IN ('findstr /s /m /R "%searchregex%" "%sourcedir%\*meta.xml"') DO (
 rem here, %%i contains the name of the xml file.
 rem detect whether the subdirectory name ends with (year) [country]
 ECHO %%~dpi|FINDSTR /R ".*(.*) \[.*\]\\" >nul
 IF ERRORLEVEL 1 (rem no (year) [country] pattern found
  rem search that particular xml file for the Country tag and select the country to %%c
  FOR /f "delims=" %%c IN ('findstr /R "%searchregex%" "%%i"') DO (
   SET "countryline=%%c"
   SET "countryline=!countryline:*<=<!"
   FOR /f "tokens=2delims=<>" %%s IN ("!countryline!") DO (
    rem repeat the search of the xml file for the Year tag and select the year to %%y
    FOR /f "tokens=2delims=<> " %%y IN ('findstr /R "%searchregex:Country=Year%" "%%i"') DO (
     rem now rename - note that a rename target may only be the NAME(extension)
     FOR /f "delims=" %%b IN ("%%~dpi.") DO ECHO REN "%%~fb" "%%~nxb (%%y) [%%s]"
    )
   )
  )
 )
)

GOTO :EOF

Эта версия устанавливает countryline на содержимое строки country, затем заменяет любые символы, появлявшиеся до и включающие первый <, на <, используя отложенное расширение, затем токенизация применяется к результирующей строке, используя <> только для сохранения места в «Буркина-Фасо».

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