@ECHO OFF
SETLOCAL
SET "relroot=u:\photos collection 01"
SET "oldmask=im age"
SET "newmask=new name"
SET "ext=jpg"
SET "skipped="
::
:: step 1 - ensure no 'newname*.ext' exists in the subtree
::
FOR /f %%i IN (
'DIR /s/b/a-d "%relroot%\%newmask%*.%ext%" 2^>nul^|FIND /c /v "" '
) DO IF NOT %%i==0 ECHO Files matching new mask already exist&GOTO :EOF
::
:: step 2 - list target files
::
:temploop
SET tempfile=%temp%\Photo%random%
IF EXIST "%tempfile%*" GOTO temploop
:: now have random tempfile name
(
FOR /f "delims=" %%i IN (
'DIR /s/b/a-d "%relroot%\%oldmask%*.%ext%" '
) DO (
ECHO %%~ni*%%~fi
)
)>"%tempfile%1"
::
:: Now do the rename
::
SET count=1000
SET prev=%newmask%
FOR /f %%i IN ('find /c "*" ^<"%tempfile%1"') DO IF %%i gtr 1000 ECHO %%i files - exceeds capacity&GOTO :eof
FOR /f "delims=*" %%i IN ('SORT "%tempfile%1"') DO (CALL :incren "%%i")
IF DEFINED skipped ECHO some files were NOT renamed&DIR /s/b/a-d "%relroot%\%oldmask%*.%ext%"
DEL "%tempfile%1"
GOTO :eof
:incren
:: repeat?
IF "%prev%"==%1 GOTO :EOF
:: no - process next name found
SET "prev=%~1"
FOR %%n IN (firstname secondname) DO (SET %%n=)
:: scan the tempfile, looking for matches to name found
FOR /f "usebackqtokens=1,2delims=*" %%m IN ("%tempfile%1") DO IF /i "%%m"=="%prev%" (
IF DEFINED firstname SET skipped=Y&IF NOT DEFINED secondname SET secondname=%%n
IF NOT DEFINED firstname SET firstname=%%n
)
IF DEFINED secondname SET firstname=%secondname%
ECHO REN "%firstname%" "%newmask%%count:~-3%.%ext%"
SET /a count+=1
GOTO :eof
好吧,毕竟不是太难。
不太符合您的规范 - 我避免删除文件,所以我没有重命名任何具有重复名称的目标。
尝试处理 IMO 愚蠢的文件名时给予了太多的关注。如果你!%^)=
在你的文件名中使用类似的字符——好吧——你很聪明——你会想出来的。
所以,假设合理的文件名字符和空格,工作!
首先设置您的relative root
(起始子目录)名称、要使用的文件掩码、新旧文件以及扩展名。我使用set "var=string"
语法来避免应用不可见且可能导致混乱的杂散终端空间。另请注意,在字符串赋值中,'=' 两边的空格很重要。
第一步是记录在案的。如果树中已经有与新名称匹配的文件,不确定该怎么做 - 所以什么也不做。如果一切正常,计算从dir /s/b/a-d
(目录,带有子目录,基本形式(因此没有标题)和没有目录名称)出现的行数应该大约为 0。
我喜欢使用 showm 方法设置临时文件。如果没有%temp%
与选择的随机名称匹配的名称,那么使用该名称+您喜欢的任何附录应该是安全的(因此,如果需要,您可以创建许多临时文件。)
下一步是再次以基本形式获取旧名称文件的子目录 - 但这次输出到临时文件。输出的是每个文件的一行,结构为仅 NAME 部分 ( %%~ni
) 一个星号和完整的文件名 ( %%~fi
)。星号充当列分隔符并且是安全的,因为*
不能出现在文件名中。
接下来是重命名阶段。我们从COUNT
1000 开始,以便我们可以使用最后 3 个字符来创建名称。如果您想从 001 开始,请改用 1001。PREV
被初始化为一个不能作为要重命名的文件名出现的值。
再次计算要重命名的名称。如果太多,弃船。
下一步是对临时文件进行排序,因此将按原始基本文件名的顺序(每行中的“*”之前)处理结果,然后,如果名称匹配,则按子目录名称的字母顺序(因为 name* parent 将在 name*parent\subdir) 之前排序。然后将遇到的每个 NAME 传递给:incren
例程 - 引用以适应文件名中的空格要求。
INCREN 例程做的第一件事是检查该名称是否与之前遇到的名称重复。如果是,则忽略该名称(因为它已被处理)。PREV
然后设置为遇到的下一个名称。SET "prev=%~1"
从第一个参数中删除引号,然后将结果分配给prev
和封闭的引号防止杂散空格对接。firstname
然后secondname
设置为 [nothing]
然后我们再次扫描临时文件,寻找匹配的名称作为第一个标记并将第二个标记(完整文件名)分配给%%n
找到第一个时,未设置名字,因此将其设置为完整文件名。如果找到第二个名称,则firstname
已经设置,因此设置SKIPPED
为标记遇到问题。如果尚未设置第二个文件名,则设置为该secondname
完整文件名。如果找到更多匹配项,则由于现在已设置,将不再进行任何操作。secondname
处理完文件后,我们将firstname
设置为第一个完整文件名(因为第一个遇到的是相对根目录),并且secondname
只有在找到 2 个或更多匹配名称时才会设置。在这种情况下,设置firstname
为遇到的第二个名称的值,该名称将位于较低的子目录中。
现在进行重命名。我刚刚ECHO
编辑了它,但要激活,请ECHO
从ECHO REN...
行中删除。我们知道firstname
包含要重命名的文件的全名,并且我们知道新文件名的结构将是新的掩码+最后3个字符COUNT
+一个点+选定的扩展名。
并为下一次重命名准备好计数...
这是删除后的测试运行ECHO
:
============= before =========
u:\photos collection 01\im age 612.jpg
u:\photos collection 01\im age 003.jpg
u:\photos collection 01\im age 005.jpg
u:\photos collection 01\im age 610.jpg
u:\photos collection 01\im age 009.jpg
u:\photos collection 01\im age 609.jpg
u:\photos collection 01\im age 505.jpg
u:\photos collection 01\selection 01\im age 001.jpg
u:\photos collection 01\selection 01\im age 004.jpg
u:\photos collection 01\selection 01\im age 005.jpg
u:\photos collection 01\selection 01\im age 006.jpg
============= run =========
some files were NOT renamed
u:\photos collection 01\im age 005.jpg
============= after =========
u:\photos collection 01\new name009.jpg
u:\photos collection 01\new name001.jpg
u:\photos collection 01\im age 005.jpg
u:\photos collection 01\new name008.jpg
u:\photos collection 01\new name005.jpg
u:\photos collection 01\new name007.jpg
u:\photos collection 01\new name006.jpg
u:\photos collection 01\selection 01\new name000.jpg
u:\photos collection 01\selection 01\new name002.jpg
u:\photos collection 01\selection 01\new name003.jpg
u:\photos collection 01\selection 01\new name004.jpg
请注意,这是在 FAT 驱动器上执行的,因此实际文件的顺序在两个列表中是相同的。