通过解析文件夹中的XML文件来重命名文件夹

时间:2019-05-05 13:19:37

标签: xml windows batch-file

我想解析文件夹中的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>

Parse XML files in folder and rename them with values from three nodes

我尝试了几种方法,但是最后出现斜杠问题

@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 个答案:

答案 0 :(得分:1)

对于此任务,我建议使用以下批处理文件:

@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串联在一起。在语法上用E:\Test定义此变量不是100%正确,因为这会导致文件名字符串E:\Test\\meta.xml包含两个反斜杠而不是在文件路径和文件名之间仅包含一个反斜杠。

对于命令 DIR 在源目录或其任何子目录中找到的每个文件meta.xml,命令 FOR 执行可执行文件 FINDSTR 会搜索区分大小写(XML标记区分大小写)的国家/地区 OR 年元素,其字符串值至少为一个字符。 FINDSTR 将搜索正则表达式中的空格字符解释为 OR ,但这并没有得到很好的记录。

如果在Country中搜索国家和年份字符串之后都定义了环境变量Yearmeta.xml,则将当前XML文件的文件路径分配给环境变量{{1 }}总是以反斜杠结束。

现在是时候启用delayed expansion了。如果文件夹名称包含一个或多个感叹号,则不应启用该功能,因为在这种情况下,在批处理文件开始时已启用延迟扩展,则该批处理文件将根本无法工作。请阅读this answer,以获取有关命令 SETLOCAL ENDLOCAL 的详细信息,这不仅仅是启用延迟的环境变量扩展所发生的事情。

带有路径的整个文件夹名称将用 ECHO 输出,并重定向到处理 FINDSTR STDIN ,以检查文件夹名称是否尚未在圆括号中以(正确)年结尾,在方括号中以(正确)国家结尾。此附加测试的灵感来自 LotPings 编写的代码。

仅当文件夹名称尚未以(正确的)年份和国家/地区结尾并且不使用反斜杠结尾的最后一个用{{1 }},如果该字符串表示带有文件扩展名的文件名或文件夹名称,则在最后一个反斜杠之后引用该字符串。 FilePath引用具有完整路径的当前文件夹名称,结尾没有反斜杠。

注释1:批处理文件不适用于将源目录作为驱动器的根目录执行。

注释2:如果文件%%~nxJ现在包含不同的年份或国家,则该代码不会从文件夹名称中删除错误的年份/国家。因此,如果文件夹%%~J中的meta.xml现在包含Folder1 (2015) [US]Folder1 (2019) [India],则名为meta.xml的文件夹不会重命名为Folder1 (2015) [US]

注释3:如果XML文件在一行上包含多个XML元素,则 FOR 进行的行解析将不起作用。 <Country>India</Country><Year>2019</Year>元素必须位于单独的行上,并且没有其他XML元素。因此,如果Country在一行中包含例如Year,则无法使用此批处理代码。 Windows命令处理器没有像PowerShell支持那样以XML方式解析XML内容的功能。

要了解所使用的命令及其工作方式,请打开命令提示符窗口,在其中执行以下命令,并非常仔细地阅读每个命令显示的所有帮助页面。

  • meta.xml
  • <Country>India</Country><Year>2019</Year>
  • dir /?
  • echo /?
  • endlocal /?
  • findstr /?
  • for /?
  • if /?
  • ren /?

答案 1 :(得分:1)

  • 我将使用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的提示,更改了批次。并在FAT32上成功测试

答案 2 :(得分:0)

@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]中,因此,如果drive:path与正则表达式{anystring}({anystring}) [{anystring}]\相匹配,则您不想对其进行处理,并且errorlevel设置为0。注意:为了安全起见,也许将/E开关添加到findstr上,以便仅在外部叶子上匹配模式。)

对于那些需要重命名的文件,请使用meta.xmlmeta.xml标签搜索特定的country文件(假设您想要以searchregex结尾的任何文件名),然后搜索再次使用相同的文件,这次用Country将搜索中的Year替换为\,因为我当时认为这很合适,所以我使用字符串替换。

如果到达内部命令,则可以通过在路径字符串后附加.来删除终端for/f,然后在delims=常量字符串上使用{{ 1}}来克服标记化。

最后构造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行的内容,然后使用延迟扩展将<之前出现的所有字符替换为<,然后进行标记化使用<>应用于结果字符串,只是为了保留“布基纳法索”中的空格。

相关问题