我想解析文件夹中的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文件中按短语年份和国家/地区重命名文件夹
答案 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
中搜索国家和年份字符串之后都定义了环境变量Year
和meta.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文件:: 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.xml
为meta.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
行的内容,然后使用延迟扩展将<
之前出现的所有字符替换为<
,然后进行标记化使用<>
应用于结果字符串,只是为了保留“布基纳法索”中的空格。