Board logo

标题: [其他] 【已解决】BAT脚本批量修改某目录下几千个文件名 [打印本页]

作者: zhengwei007    时间: 2024-9-4 19:59     标题: 【已解决】BAT脚本批量修改某目录下几千个文件名

我的目录下有几千个文件,文件顺序是1-1.jpg,1-2.jpg,1-3.jpg,2-1.jpg,2-2.jpg,2-3.jpg……
我想通过批处理,让这些文件名全部修改为如下顺序:
Shot00000.jpg
Shot00001.jpg
Shot00002.jpg
Shot00003.jpg
Shot00004.jpg
Shot00005.jpg

相当于让1-1.jpg改成了Shot00000.jpg。1-2.jpg改成了Shot00001.jpg……2-3.jpg改成了Shot00005.jpg
感谢各位大佬。
作者: ppll2030    时间: 2024-9-4 20:46

本帖最后由 ppll2030 于 2024-9-4 23:38 编辑
  1. @echo off&setlocal enabledelayedexpansion
  2. (for /f "tokens=1-3 delims=-." %%a in ('dir /b /a-d *.jpg') do (
  3. set a=00000%%a&set b=00000%%b
  4. echo !a:~-5!-!b:~-5!=%%a-%%b.%%c
  5. ))>$
  6. set n=0
  7. for /f "tokens=2 delims==" %%i in ('sort $') do (
  8. set m=0000!n!
  9. rem 确认无误再去除echo
  10. echo ren "%%i" "Shot!m:~-5!"%%~xi
  11. set/a n+=1
  12. )
  13. del /q $ &pause
复制代码

作者: aloha20200628    时间: 2024-9-4 21:12

回复 1# zhengwei007

如果文件名编号没有位数对齐,可能出现 1-1.jpg,1-2.jpg,...,1-10.jpg,... 被 dir /b *.jpg 错位列表的结果,如下
...
1-1.jpg
1-10.jpg
...
1-2.jpg
...

须楼主确认。

作者: zhengwei007    时间: 2024-9-4 21:58

回复 3# aloha20200628

如果出现1-10.jpg,1-11.jpg,那么需要按照这个顺序去改变文件名。不能是1-1.jpg,1-10.jpg,1-2.jpg这样的顺序。
作者: 77七    时间: 2024-9-4 22:14

  1. @echo off
  2. cd /d "%~dp0"
  3. setlocal enabledelayedexpansion
  4. for /f "tokens=1-3 delims=-." %%a in ('dir /b /a-d *.jpg') do (
  5. set a=00000%%a
  6. set b=00000%%b
  7. set _!a:~-5!_!b:~-5!=%%a-%%b.%%c
  8. )
  9. set n=-1
  10. for /f "tokens=2 delims==" %%a in ('set _') do (
  11. set /a n+=1
  12. set m=00000!n!
  13. ren "%%a" "Shot!m:~-5!.jpg"
  14. )
  15. endlocal
  16. pause
复制代码

作者: aloha20200628    时间: 2024-9-4 22:22

本帖最后由 aloha20200628 于 2024-9-5 12:22 编辑

回复 4# zhengwei007

须从本坛下载 sort.exe v7.6 (http://bcn.bathome.net/tool/7.6/sort.exe)以下批处代码中采用的 sort76.exe 即为此版,与批处脚本放在同目录...
采用 sort76.exe 以便确保 dir/b *.jpg 列表能被处理成楼主所要的排序,例如:

1-1.jpg
1-2.jpg
...
1-10.jpg
...
2-1.jpg
...
11-1.jpg
...

  1. @echo off &setlocal enabledelayedexpansion &set "n=0"
  2. for /f "delims=" %%F in ('dir /b/a-d *.jpg^|sort76 -t "-" -n -k1 -k2') do (
  3. set "nF=0000!n!" &set "nF=!nF:~-5!"
  4. ren "%%F" "Shot!nF!.jpg"
  5. set/a "n+=1"
  6. )
  7. pause&exit/b
复制代码

作者: zhengwei007    时间: 2024-9-5 00:24

已经搞定,谢谢楼上所有的朋友。
作者: qixiaobin0715    时间: 2024-9-5 08:48

本帖最后由 qixiaobin0715 于 2024-9-5 11:39 编辑

不使用临时文件,不预设变量(或者说设置极少数变量x1/x2/z1/z2/n),不使用第3方:
  1. @echo off
  2. setlocal enabledelayedexpansion
  3. set /a z1=z2=0
  4. for /f "tokens=1* delims=-" %%i in ('dir /b /a-d *-*.jpg') do (
  5.     set /a x1=%%i,x2=%%~nj
  6.     if !x1! gtr !z1! set /a z1=x1
  7.     if !x2! gtr !z2! set /a z2=x2
  8. )
  9. set n=99999
  10. for /l %%i in (1,1,!z1!) do (
  11.     for /l %%j in (1,1,!z2!) do (
  12.         if exist %%i-%%j.jpg (
  13.             set /a n+=1
  14.             ren %%i-%%j.jpg Shot!n:~1!.jpg
  15.         )
  16.     )
  17. )
  18. pause
复制代码

作者: aloha20200628    时间: 2024-9-5 12:10

本帖最后由 aloha20200628 于 2024-9-5 12:20 编辑


用纯P的goto/call方法确实能自力更生(代码如下),不用 sort76.exe 外援,关键是可以实现动态循环(能够实时修改循环条件及变量),这是 for /L 静态循环的 ‘痛点’,但代价是有可能比6楼代码效率低...
  1. @echo off &setlocal enabledelayedexpansion &set "c=-1"
  2. :abc
  3. set/a "a+=1"
  4. if not exist "!a!-1.jpg" endlocal&pause&exit/b
  5. call :xyz
  6. :xyz
  7. set/a "b+=1,c+=1" &set "sF=!a!-!b!.jpg" &set "nF=0000!c!" &set "nF=!nF:~-5!"
  8. if exist "!sF!" ren "!sF!" "shot!nF!.jpg" & goto :xyz
  9. set "b=" &set/a "c-=1" &goto :abc
复制代码

作者: qixiaobin0715    时间: 2024-9-5 13:09

本帖最后由 qixiaobin0715 于 2024-9-5 13:25 编辑

就本题来说goto/call虽然能够避免for /l 的空转现象,但goto/call带标签的循环实际效率也是有待商榷的,要进行比较测试有一定的难度,因为测试素材不同对两者的影响差别很大。不必妄下断言,还是存疑吧。另外楼上代码第4行“!a!-1.jpg”最好改为“!a!-*.jpg” 防止出现源文件中缺失“-1”而存在“-2、-3...”的情况而误判。


:xyz下面的代码好像也有问题,比如数值不连续会出问题,比如只有:1-1.jpg 1-3.jpg 1-5.jpg...


不大使用goto和call,但是我觉得上面改为“!a!-*.jpg”也是有问题的,如果是这样... 10-*,11-*,13-*...,不知是否会出问题。
作者: aloha20200628    时间: 2024-9-5 14:39

本帖最后由 aloha20200628 于 2024-9-5 14:46 编辑


谢谢10楼关注 6楼代码和9楼代码只是示例一下两极版本,或者把全部排序交给 sort76.exe 一气呵成,实现高效率,或者假设两个字段的排序均是自然连续的,能用纯P代码尽量简化...

作者: qixiaobin0715    时间: 2024-9-5 15:15

本帖最后由 qixiaobin0715 于 2024-9-5 15:17 编辑

goto/call这两个命令我用的极少,不是太熟悉。感觉9楼修改修改2个exist判断语句也能实现:
第1句修改为: *-*.jpg;
保留第2句前面部分;从&处另起一行,增加一个exist判断,看看是否存在!a!-*.jpg,存在就goto :xyz,否则就goto :abc;
只是提供个思路,具体修改细节不知,我对这2个命令有点晕。但是这样的话就不那么纯动态了。
作者: 77七    时间: 2024-9-5 15:45

if 到底
  1. @echo off
  2. cd /d "%~dp0"
  3. set /a a=b=1,n=0
  4. :loop
  5. set m=00000%n%
  6. if exist "*-*.jpg" (
  7. if exist "%a%-*.jpg" (
  8. if exist "%a%-%b%.jpg" (
  9. ren "%a%-%b%.jpg" "Shot%m:~-5%.jpg"
  10. set /a n+=1
  11. )
  12. set /a b+=1
  13. ) else (
  14. set /a a+=1,b=1
  15. )
  16. goto :loop
  17. )
  18. pause
复制代码

作者: 77七    时间: 2024-9-5 16:21

本帖最后由 77七 于 2024-9-5 16:25 编辑
  1. 测试文件
  2. for /l %%l in (1,1,100) do (
  3.         for /l %%m in (1,1,50) do (
  4.                 cd.>%%l-%%m.jpg
  5.         )
  6. )
  7. 2楼
  8. 15:48:19.79
  9. 15:48:25.44
  10. 5楼
  11. 15:49:02.77
  12. 15:49:14.39
  13. 6楼
  14. 15:50:20.02
  15. 15:50:25.33
  16. 8楼
  17. 15:51:17.52
  18. 15:51:23.19
  19. 9楼
  20. 15:52:11.89
  21. 15:52:22.04
  22. 13楼
  23. 15:53:28.72
  24. 15:53:39.69
  25. 测试文件
  26. for /l %%l in (1,3,300) do (
  27.         for /l %%m in (1,3,150) do (
  28.                 cd.>%%l-%%m.jpg
  29.         )
  30. )
  31. 2楼
  32. 15:56:02.20
  33. 15:56:08.06
  34. 5楼
  35. 15:56:41.69
  36. 15:56:57.64
  37. 6楼
  38. 15:57:54.50
  39. 15:57:59.04
  40. 8楼
  41. 15:58:36.08
  42. 15:58:43.98
  43. 9楼
  44. 失败
  45. 13楼
  46. 16:02:56.72
  47. 16:03:49.45
复制代码
仅测试一轮

文件序号连续时,2、6、8楼耗时5-7秒左右,5、9、13楼耗时11-12秒左右
文件序号不连续时,5楼16秒,9楼失败,13楼55秒,其余变化不大
作者: qixiaobin0715    时间: 2024-9-5 16:51

本帖最后由 qixiaobin0715 于 2024-9-6 11:20 编辑

回复 13# 77七
既然这么喜欢if,给你找个素材练练手,大概是两三年前的一个帖子,由于关注度不大,原贴未找到。一个大佬用迭代法解决的,在这里设定就用“if到底”求解,文本如下:
  1. 1,8
  2. 2,-8
  3. 3,5
  4. 4,0
  5. 5,25
  6. 6,30
  7. 7,18
  8. 8,50
  9. 9,-12
  10. 10,-22
  11. 11,-5
  12. 12,4
  13. 13,11
  14. 14,20
  15. 15,55
  16. 16,33
  17. 17,-22
  18. 18,-10
  19. 19,-3
  20. 20,10
  21. 21,9
  22. 22,5
  23. 23,0
  24. 24,-5
  25. 25,14
  26. 26,22
  27. 27,50
  28. 28,89
  29. 29,-9
  30. 30,-33
  31. 31,-12
  32. 32,-66
  33. 33,8
  34. 34,-9
  35. 35,8
复制代码
前面是序号,后面是数值。
找出连续3个数值小于等于6;接着连续4个数大于等于10;再接着连续3个数小于等于-2,共10个连续数值。不止一组数值符合以上条件啊,重叠也算。找到后显示序号比如10-19。
要注意第一个条件的数值包含第三个条件的数值。
原贴都是连续3个数值,记得我当时是取巧解决的,这里第二个条件是连续4个数值,增加了一些难度。
没什么实际用处,只是练练手,博得一笑而已,别当回事。
作者: 77七    时间: 2024-9-5 17:56

回复 15# qixiaobin0715


   大佬,这个比重命名复杂多了,我写不出来。
作者: qixiaobin0715    时间: 2024-9-6 09:41

本帖最后由 qixiaobin0715 于 2024-9-6 14:09 编辑

回复 16# 77七
是挺复杂的,我现在也没有写出来
但思路有了。
分别从上到下统计符合要求的数值连续出现的次数。
需要分级设定锚点:
第1级,如果出现不符合数值(小于10且大于6),所有的先前统计次数均要清零,从下一行开始重新统计;
第2级,对于出现大于等于10的数值。
          如果首次出现,向上追溯,如果最近3行不是连续数值小于等于6,所有的统计次数均要清零,重新统计;
          如果连续出现多于4次,所有的统计次数均要清零,重新统计;
第3级,对于出现小于或等于-2的数值的情况。
          如果首次出现,向上追溯,如果第2级未通过(即次数为1-3),所有的统计次数均要清零,将本次数值统计到小于等于6的次数中;
应当还有一些要考虑的细节,较为繁琐,不再一一罗列。大致就是这样。
可能还有更好的思路。
作者: qixiaobin0715    时间: 2024-9-6 14:52

本帖最后由 qixiaobin0715 于 2024-9-6 17:09 编辑

回复 16# 77七
烧脑的if判断语句!!!
可能会有bug。
x变量分别表示设定的连续数值出现的次数;
n变量分别表示实际的连续数值动态出现的次数;
  1. @echo off
  2. set /a x1=3,x2=4,x3=3
  3. set /a n1=n2=n3=0
  4. setlocal enabledelayedexpansion
  5. for /f "tokens=1* delims=," %%i in (a.txt) do (
  6.     if %%j geq 10 (
  7.         if !n1! lss !x1! (
  8.             set /a n1=n2=n3=0
  9.         ) else (
  10.             if !n3! neq 0 (
  11.                 set /a n1=n2=n3=0
  12.             ) else (
  13.                 set /a n2+=1
  14.                 if !n2! gtr !x2! set /a n1=n2=n3=0
  15.             )
  16.         )
  17.     ) else if %%j leq 6 (
  18.         if !n2! equ 0 (
  19.             set /a n1+=1
  20.         ) else (
  21.             if !n2! equ !x2! (
  22.                 if %%j leq -2 (
  23.                     set /a n3+=1
  24.                     if !n3! equ !x3! (
  25.                         set /a m=%%i-10+1
  26.                         echo,!m!-%%i
  27.                         set /a n1=n3
  28.                         set /a n2=n3=0
  29.                     )
  30.                 ) else (
  31.                     set /a n1=n3+1
  32.                     set /a n2=n3=0
  33.                 )
  34.             ) else (
  35.                 set /a n1=1
  36.                 set /a n2=0
  37.             )
  38.         )
  39.     ) else (
  40.         set /a n1=n2=n3=0
  41.     )
  42. )
  43. pause
复制代码
还没想到更简单的方法,现在只能这样了。
写代码的过程中发现,考虑实际问题时和17楼的思路还是有很大的差异,上下左右都有牵扯,有一点考虑不到就会出问题。
作者: 77七    时间: 2024-9-6 19:35

回复 18# qixiaobin0715


   
谢谢大佬分享!确实太复杂了,和出题挑战区的数学题目一样,反正我暂时不想想这个。
作者: aloha20200628    时间: 2024-9-6 21:19

本帖最后由 aloha20200628 于 2024-9-6 21:33 编辑

回复 15# qixiaobin0715

幸亏能用一串 ‘逻辑与’ 的 if 句式
假设35个数用如下格式存于 1.txt
1,8
2,-8
3,5
4,0
5,25
6,30
7,18
8,50
9,-12
10,-22
11,-5
12,4
13,11
14,20
15,55
16,33
17,-22
18,-10
19,-3
20,10
21,9
22,5
23,0
24,-5
25,14
26,22
27,50
28,89
29,-9
30,-33
31,-12
32,-66
33,8
34,-9
35,8
  1. @echo off &setlocal enabledelayedexpansion
  2. for /f "tokens=1,2 delims=, " %%a in (1.txt) do set/a "n+=1" &set "_%%a=%%b"
  3. set/a "k=!n!-9"
  4. for /l %%n in (1,1,!k!) do (
  5. set/a "m=%%n+9,i=1"
  6. for /l %%v in (%%n,1,!m!) do set "$!i!=!_%%v!" &set/a "i+=1"
  7. if !$1! leq 6 if !$2! leq 6 if !$3! leq 6 if !$4! geq 10 if !$5! geq 10 if !$6! geq 10 if !$7! geq 10 if !$8! leq -2 if !$9! leq -2 if !$10! leq -2 (
  8. echo,同时满足3个条件的10个连续数(行号)= {%%n-!m!}
  9. )
  10. )
  11. endlocal&pause&exit/b
复制代码

作者: buyiyang    时间: 2024-9-6 23:23

回复 15# qixiaobin0715


    这个也可以用迭代法
  1. @echo off
  2. setlocal enabledelayedexpansion
  3. set /a n=n1=n2=n3=p=0
  4. :loop
  5. set /a p+=1
  6. setlocal
  7. for /f "%skip%tokens=1-2 delims=," %%i in (1.txt) do (
  8.     set /a n+=1
  9.     if %%j leq 6 (
  10.         if !n! leq 3 set /a n1+=1
  11.         if !n! equ 1 set "s=%%i"
  12.         )
  13.     if %%j geq 10 if !n! geq 4 if !n! leq 7 set /a n2+=1
  14.     if %%j leq -2 if !n! geq 8 set /a n3+=1
  15.     if !n! equ 10 (
  16.         rem echo,!n1!,!n2!,!n3!
  17.         if !n1! equ 3 if !n2! equ 4 if !n3! equ 3 echo,!s!-%%i
  18.         endlocal&set "skip=skip=%p%"&goto :loop
  19.         )
  20.     )
  21. pause&exit
复制代码

作者: qixiaobin0715    时间: 2024-9-9 08:52

本帖最后由 qixiaobin0715 于 2024-9-9 09:29 编辑

实际上20、21楼的代码都是迭代法,20楼是逐行错位迭代。虽然在这里与15楼的“if到底”的要求不是太合辙,看样子迭代法是解决此类问题的其中一个捷径。
如果要用迭代法的话还是原贴中那位大佬代码更简洁,直接原地迭代:
  1. set a1=!a2!
  2. set a2=!a3!
  3. ...
  4. set a9=!a10!
  5. set a10=%%b
  6. if defined a1 if !a1! leq 6 if !a2! leq 6...
复制代码
后面部分和20楼差不多。
作者: qixiaobin0715    时间: 2024-9-9 09:38

本帖最后由 qixiaobin0715 于 2024-9-11 11:57 编辑

回复 21# buyiyang
每次读取10行文本就跳转感觉有点浪费,这样是否要节约些:
  1. @echo off
  2. setlocal enabledelayedexpansion
  3. set /a n=n1=n2=n3=p=0
  4. :loop
  5. set /a p+=1
  6. setlocal
  7. for /f "%skip%tokens=1-2 delims=," %%i in (a.txt) do (
  8.     set /a n+=1
  9.     if %%j leq 6 (
  10.         if !n! leq 3 set /a n1+=1
  11.         if !n! equ 1 set "s=%%i"
  12.         )
  13.     if %%j geq 10 if !n! geq 4 if !n! leq 7 set /a n2+=1
  14.     if %%j leq -2 if !n! geq 8 set /a n3+=1
  15.     if !n! equ 10 (
  16.         rem echo,!n1!,!n2!,!n3!
  17.         if !n1! equ 3 if !n2! equ 4 if !n3! equ 3 echo,!s!-%%i
  18.         )
  19.     if !n! equ 10 set /a n=n1=n2=n3=p=0
  20.     )
  21. endlocal
  22. set "skip=skip=%p%"
  23. if %p% lss 10 goto :loop
  24. pause&exit
复制代码

作者: qixiaobin0715    时间: 2024-9-9 11:03

回复 11# aloha20200628
实际上对于本题来说,只是处理几千条信息而已,效率问题可以忽略。
退一步来说,在for循环中反复调用第三方也会拖累一定的处理速度。在for循环外使用第三方生成临时文件,再用for循环读取临时文件可能效率会更高一些。
作者: aloha20200628    时间: 2024-9-9 11:43

本帖最后由 aloha20200628 于 2024-9-9 11:49 编辑

回复 24# qixiaobin0715

      其实众人给求助者的绝大部分代码都假定是处理小数据,dir和那些便于预装的第三方操作就顺便直接放在 for ... () 的命令表达式中,不用临时文件以免代码倒腾...
      个人经验是当被处理数据过千行就一定采用临时文件的方法,跳出 for...() 的狭窄 ‘管道井’,尤其是对硬件配置较低的实况,而一旦如此,那些被c/c++打造的第三方会充分发挥速度优势,是纯P代码远所不及的,因此能用此法叫第三方代劳越多,整个批处脚本的效率就会越高...

作者: qixiaobin0715    时间: 2024-9-9 12:54

cmd本身就不适合处理较为复杂的或者数据量较大的问题,即使加入第三方。
作者: qixiaobin0715    时间: 2024-9-9 14:46

本帖最后由 qixiaobin0715 于 2024-9-9 16:34 编辑

这样与18楼代码相比要简单一些:
  1. @echo off
  2. setlocal enabledelayedexpansion
  3. for /f "tokens=1* delims=," %%i in (a.txt) do (
  4.     if %%j geq 10 (
  5.         set a=!a!3
  6.     ) else if %%j leq -2 (
  7.         set a=!a!1
  8.         if "!a:~-7!"=="3333111" (
  9.             if not "!a:~9!"=="" (
  10.                 set b=!a:~,3!
  11.                 set b=!b:2=!
  12.                 if "!b:1=!"=="" (
  13.                     set /a n=%%i-10+1
  14.                     echo,!n!-%%i
  15.                 )
  16.             )
  17.         )
  18.     ) else if %%j leq 6 (
  19.         set a=!a!2
  20.     ) else (
  21.         set a=!a!4
  22.     )
  23.     set a=!a:~-9!
  24. )
  25. pause
复制代码

作者: qixiaobin0715    时间: 2024-9-11 14:32

简化一下楼上代码:
  1. @echo off
  2. setlocal enabledelayedexpansion
  3. for /f "tokens=1* delims=," %%i in (a.txt) do (
  4.     if %%j geq 10 (
  5.         set a=!a!3
  6.     ) else if %%j leq -2 (
  7.         set a=!a!1
  8.         if "!a:~-7!"=="3333111" (
  9.             if "!a:2=1!"=="1113333111" (
  10.                 set /a n=%%i-10+1
  11.                 echo,!n!-%%i
  12.             )
  13.         )
  14.     ) else if %%j leq 6 (
  15.         set a=!a!2
  16.     ) else (
  17.         set a=!a!4
  18.     )
  19.     set a=!a:~-9!
  20. )
  21. pause
复制代码





欢迎光临 批处理之家 (http://www.bathome.net/) Powered by Discuz! 7.2