Как переименовать файлы на основе тега содержимого XML? - PullRequest
1 голос
/ 15 февраля 2020

Я новичок в написании пакетных скриптов и мне нужна помощь. У меня есть папка, которая имеет несколько подпапок с файлами, перечисленными в структуре ниже:

  • FOLDER 0001
    • 0001.a00
    • 0001. a01
    • 0001.a02
    • 0001.a03
    • annotations.xml
  • FOLDER 0002
    • 0001.a00
    • 0001.a01
    • 0001.a02
    • 0001.a03
    • 0002.b00
    • 0002 .b01
    • 0002.b02
    • 0002.b03
    • annotations.xml
  • FOLDER 0003
    • 0001.a00
    • 0001.a01
    • 0001.a02
    • 0001.a03
    • annotations.xml

Каждая папка имеет annotations.xml. Этот файл имеет различные теги XML.

I wi sh для извлечения первых двух деталей между тегом a1 со значением атрибута New и переименованием (или добавлением) файлов *.[a-z][0-9][0-9], таких как как *.a00, *.a01, *.b01, *.b02, et c.

<a1 L="New" T="xxx" etc..>ABC9876, 20200115-1630, 20200115-1730</a1>

Я хочу переименовать файлы в:

  • ABC9876. 20200115-1630.a00
  • ABC9876.20200115-1630.a01
  • ABC9876.20200115-1630.a02

Я использовал следующий скрипт:

call xpath.bat "annotations.xml" "//a1" >> renamed.txt

Созданный файл renamed.txt содержит:

ABC9876, 20200115-1630, 20200115-1730*

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

Далее я попробовал следующее:

@echo off
setlocal EnableDelayedExpansion
for /f "tokens=1-2 delims=," %%a in (renamed.txt) do (
    echo ****************
    echo %%a echo %%b
    echo ****************
    set "new=%%a.%%b"
    set new=!new: =!
    echo !new!
    ren 0004.a03 !new!.mp3
)
pause

Я могу переименовать только один файл, но я не знаю, как это сделать переименуйте все файлы, сохраняя их существующие расширения. В приведенном выше примере я попытался переименовать один в mp3.

1 Ответ

0 голосов
/ 16 февраля 2020

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

@for /F "delims=" %%I in ('dir "%~dp0annotations.xml" /A-D /B /S 2^>nul') do for /F "tokens=2 delims=<>" %%J in ('%SystemRoot%\System32\findstr.exe /R /C:"<[^<>]*=\"New\" [^<>]*>.*,.*," "%%I"') do for /F "tokens=1,2 delims=, " %%K in ("%%J") do for /F "delims=" %%O in ('dir "%%~dpI" /A-D /B ^| %SystemRoot%\System32\findstr.exe /I /R "^[0123456789][0123456789][0123456789][0123456789]\.[a-z][0123456789][0123456789]$"') do ren "%%~dpI%%O" "%%K.%%L%%~xO"

Лучше читается следующий многострочный вариант:

@echo off
for /F "delims=" %%I in ('dir "%~dp0annotations.xml" /A-D /B /S 2^>nul') do (
    for /F "tokens=2 delims=<>" %%J in ('%SystemRoot%\System32\findstr.exe /R /C:"<[^<>]*=\"New\" [^<>]*>.*,.*," "%%I"') do (
        for /F "tokens=1,2 delims=, " %%K in ("%%J") do (
            for /F "delims=" %%O in ('dir "%%~dpI" /A-D /B ^| %SystemRoot%\System32\findstr.exe /I /R "^[0123456789][0123456789][0123456789][0123456789]\.[a-z][0123456789][0123456789]$"') do (
                echo ren "%%~dpI%%O" "%%K.%%L%%~xO"
            )
        )
    )
)
pause

Примечание: Есть команда echo оставил команду ren в приведенном выше коде, чтобы просто вывести команду переименования файла вместо выполнения команды переименования. Рекомендуется сначала запустить этот многострочный пакетный файл, чтобы убедиться, что файлы XML действительно правильно обработаны и поэтому правильно создано новое имя файла.


Первый FOR выполняет в фоновом режиме еще один командный процесс с %ComSpec% /c, а командная строка между ' добавляется в качестве дополнительных аргументов. Таким образом, выполняется Windows, установленное в C:\Windows:

C:\Windows\System32\cmd.exe /c dir "C:\batch file directory\annotations.xml" /A-D /B /S 2>nul

DIR , выполняемое отдельным процессом команды в фоновом поиске

  • в каталоге пакетных файлов и все его подкаталоги из-за опции /S
  • только для файлов из-за опции /A-D (атрибут не каталог)
  • с именем файла annotations.xml и
  • выводятся в простом формате только найденные имена файлов из-за опции /B с полным путем из-за опции /S для обработки STDOUT (стандартный вывод) фонового командного процесса.

Возможно, DIR не может найти файл, соответствующий этим критериям. В этом случае сообщение об ошибке будет выдано DIR для обработки STDERR (стандартная ошибка), которое подавляется путем перенаправления его на устройство NUL .

Прочтите статью Microsoft о Использование операторов перенаправления команд для объяснения 2>nul. Оператор перенаправления > должен быть экранирован с помощью символа вставки ^ в FOR командной строки для интерпретации в качестве литерального символа, когда интерпретатор команд Windows обрабатывает эту командную строку перед выполнением команды FOR который выполняет встроенную dir командную строку в отдельном командном процессе, запущенном в фоновом режиме.

FOR захватывает выходные данные для обработки STDOUT запущенного фонового командного процесса и обрабатывает этот вывод построчно после запуска cmd.exe закрывается после завершения выполнения DIR .

Пустые строки по умолчанию пропускаются FOR , но нет пустые строки в этом случае.

FOR будет разбивать каждую непустую строку по умолчанию на подстроки с использованием обычного пробела и горизонтальной табуляции в качестве разделителей строк и будет назначать только первый пробел / табуляцию строка указанной переменной l oop. Такое разделение строк здесь нежелательно, поскольку путь к файлу annotations.xml может содержать один или несколько пробелов. По этой причине опция delims= используется для определения пустого списка разделителей строк, который отключает режим разделения строк.

FOR будет игнорировать также строки, в которых первая подстрока, являясь всей строка в этом случае начинается с символа конца строки по умолчанию ;. Но полное имя файла, выводимое DIR , не может начинаться с точки с запятой. Полный путь к файлу всегда начинается либо с буквы диска, либо с обратным символом sh в случае UNC-пути. Таким образом, FOR в этом случае не игнорирует ни одной строки.

Первая FOR перебирает все annotations.xml, найденные в каталоге пакетного файла и его подкаталогах.


Второй FOR снова запускается в фоновом режиме еще одной командой, чтобы выполнить FINDSTR с регистрозависимым регулярным выражением на текущем annotations.xml, чтобы найти строку содержащий строку ="New" где-то внутри тега, по крайней мере с двумя разделенными запятыми строками в значении этого XML элемента.

Найденный вывод строки с помощью FINDSTR захватывается FOR и обрабатывается с разбивкой строки на подстроки с использованием угловых скобок в качестве разделителей строк из-за опции delims=<>. Только вторая строка с разделителями в виде угловых скобок, представляющая собой значение элемента XML, найденного FINDSTR , присваивается указанной переменной l oop J из-за tokens=2.


Третий FOR обрабатывает значение string элемента XML, разделяя его, используя запятую и обычный пробел в качестве разделителей строк, как указано в delims=, . Первая подстрока назначается указанной переменной l oop K, а из-за tokens=1,2 вторая подстрока, разделенная запятыми / пробелами, назначается следующей переменной l oop в соответствии с ASCII-таблицей , которая является l oop переменная L.


Четвертый FOR запускает DIR в отдельном командном процессе, чтобы найти все файлы в каталоге текущего annotations.xml. Выходные данные дополнительно фильтруются с помощью FINDSTR для окончательного вывода в STDOUT фонового командного процесса только тех имен файлов без пути к файлу, чье имя имеет ровно четыре цифры, а расширение файла начинается без учета регистра. с буквой ASCII и имеет ровно две цифры рядом. Эта фильтрация позволяет запускать пакетный файл несколько раз в одном и том же дереве каталогов, избегая переименования файлов, которые уже были переименованы при предыдущем выполнении пакетного файла.

Четвертый FOR обрабатывает файл имена без пути к файлу один за другим и запускает команду переименования с требуемым новым именем, соответственно выводит командную строку переименования.


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

  • call /? ... объясняет %~dp0 ... диск и путь к нему аргумент 0, который является текущим обработанным пакетным файлом, то есть полный путь к пакетному файлу всегда заканчивается обратным символом sh.
  • dir /?
  • echo /?
  • findstr /?
  • for /?
  • pause /?
  • ren /?
...