标题: [其他] 【已解决】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 编辑
- @echo off&setlocal enabledelayedexpansion
- (for /f "tokens=1-3 delims=-." %%a in ('dir /b /a-d *.jpg') do (
- set a=00000%%a&set b=00000%%b
- echo !a:~-5!-!b:~-5!=%%a-%%b.%%c
- ))>$
- set n=0
- for /f "tokens=2 delims==" %%i in ('sort $') do (
- set m=0000!n!
- rem 确认无误再去除echo
- echo ren "%%i" "Shot!m:~-5!"%%~xi
- set/a n+=1
- )
- 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
- @echo off
- cd /d "%~dp0"
- setlocal enabledelayedexpansion
- for /f "tokens=1-3 delims=-." %%a in ('dir /b /a-d *.jpg') do (
- set a=00000%%a
- set b=00000%%b
- set _!a:~-5!_!b:~-5!=%%a-%%b.%%c
- )
- set n=-1
- for /f "tokens=2 delims==" %%a in ('set _') do (
- set /a n+=1
- set m=00000!n!
- ren "%%a" "Shot!m:~-5!.jpg"
- )
- endlocal
- 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
...
- @echo off &setlocal enabledelayedexpansion &set "n=0"
- for /f "delims=" %%F in ('dir /b/a-d *.jpg^|sort76 -t "-" -n -k1 -k2') do (
- set "nF=0000!n!" &set "nF=!nF:~-5!"
- ren "%%F" "Shot!nF!.jpg"
- set/a "n+=1"
- )
- 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方:- @echo off
- setlocal enabledelayedexpansion
- set /a z1=z2=0
- for /f "tokens=1* delims=-" %%i in ('dir /b /a-d *-*.jpg') do (
- set /a x1=%%i,x2=%%~nj
- if !x1! gtr !z1! set /a z1=x1
- if !x2! gtr !z2! set /a z2=x2
- )
- set n=99999
- for /l %%i in (1,1,!z1!) do (
- for /l %%j in (1,1,!z2!) do (
- if exist %%i-%%j.jpg (
- set /a n+=1
- ren %%i-%%j.jpg Shot!n:~1!.jpg
- )
- )
- )
- pause
复制代码
作者: aloha20200628 时间: 2024-9-5 12:10
本帖最后由 aloha20200628 于 2024-9-5 12:20 编辑
用纯P的goto/call方法确实能自力更生(代码如下),不用 sort76.exe 外援,关键是可以实现动态循环(能够实时修改循环条件及变量),这是 for /L 静态循环的 ‘痛点’,但代价是有可能比6楼代码效率低...
- @echo off &setlocal enabledelayedexpansion &set "c=-1"
- :abc
- set/a "a+=1"
- if not exist "!a!-1.jpg" endlocal&pause&exit/b
- call :xyz
- :xyz
- set/a "b+=1,c+=1" &set "sF=!a!-!b!.jpg" &set "nF=0000!c!" &set "nF=!nF:~-5!"
- if exist "!sF!" ren "!sF!" "shot!nF!.jpg" & goto :xyz
- 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 到底- @echo off
- cd /d "%~dp0"
- set /a a=b=1,n=0
-
- :loop
- set m=00000%n%
- if exist "*-*.jpg" (
- if exist "%a%-*.jpg" (
- if exist "%a%-%b%.jpg" (
- ren "%a%-%b%.jpg" "Shot%m:~-5%.jpg"
- set /a n+=1
- )
- set /a b+=1
- ) else (
- set /a a+=1,b=1
- )
- goto :loop
- )
- pause
复制代码
作者: 77七 时间: 2024-9-5 16:21
本帖最后由 77七 于 2024-9-5 16:25 编辑
- 测试文件
- for /l %%l in (1,1,100) do (
- for /l %%m in (1,1,50) do (
- cd.>%%l-%%m.jpg
- )
- )
- 2楼
- 15:48:19.79
- 15:48:25.44
- 5楼
- 15:49:02.77
- 15:49:14.39
- 6楼
- 15:50:20.02
- 15:50:25.33
- 8楼
- 15:51:17.52
- 15:51:23.19
- 9楼
- 15:52:11.89
- 15:52:22.04
- 13楼
- 15:53:28.72
- 15:53:39.69
-
- 测试文件
- for /l %%l in (1,3,300) do (
- for /l %%m in (1,3,150) do (
- cd.>%%l-%%m.jpg
- )
- )
- 2楼
- 15:56:02.20
- 15:56:08.06
- 5楼
- 15:56:41.69
- 15:56:57.64
- 6楼
- 15:57:54.50
- 15:57:59.04
- 8楼
- 15:58:36.08
- 15:58:43.98
- 9楼
- 失败
- 13楼
- 16:02:56.72
- 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,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
复制代码
前面是序号,后面是数值。
找出连续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变量分别表示实际的连续数值动态出现的次数;- @echo off
- set /a x1=3,x2=4,x3=3
- set /a n1=n2=n3=0
- setlocal enabledelayedexpansion
- for /f "tokens=1* delims=," %%i in (a.txt) do (
- if %%j geq 10 (
- if !n1! lss !x1! (
- set /a n1=n2=n3=0
- ) else (
- if !n3! neq 0 (
- set /a n1=n2=n3=0
- ) else (
- set /a n2+=1
- if !n2! gtr !x2! set /a n1=n2=n3=0
- )
- )
- ) else if %%j leq 6 (
- if !n2! equ 0 (
- set /a n1+=1
- ) else (
- if !n2! equ !x2! (
- if %%j leq -2 (
- set /a n3+=1
- if !n3! equ !x3! (
- set /a m=%%i-10+1
- echo,!m!-%%i
- set /a n1=n3
- set /a n2=n3=0
- )
- ) else (
- set /a n1=n3+1
- set /a n2=n3=0
- )
- ) else (
- set /a n1=1
- set /a n2=0
- )
- )
- ) else (
- set /a n1=n2=n3=0
- )
- )
- 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
- @echo off &setlocal enabledelayedexpansion
- for /f "tokens=1,2 delims=, " %%a in (1.txt) do set/a "n+=1" &set "_%%a=%%b"
- set/a "k=!n!-9"
- for /l %%n in (1,1,!k!) do (
- set/a "m=%%n+9,i=1"
- for /l %%v in (%%n,1,!m!) do set "$!i!=!_%%v!" &set/a "i+=1"
- 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 (
- echo,同时满足3个条件的10个连续数(行号)= {%%n-!m!}
- )
- )
- endlocal&pause&exit/b
复制代码
作者: buyiyang 时间: 2024-9-6 23:23
回复 15# qixiaobin0715
这个也可以用迭代法- @echo off
- setlocal enabledelayedexpansion
- set /a n=n1=n2=n3=p=0
- :loop
- set /a p+=1
- setlocal
- for /f "%skip%tokens=1-2 delims=," %%i in (1.txt) do (
- set /a n+=1
- if %%j leq 6 (
- if !n! leq 3 set /a n1+=1
- if !n! equ 1 set "s=%%i"
- )
- if %%j geq 10 if !n! geq 4 if !n! leq 7 set /a n2+=1
- if %%j leq -2 if !n! geq 8 set /a n3+=1
- if !n! equ 10 (
- rem echo,!n1!,!n2!,!n3!
- if !n1! equ 3 if !n2! equ 4 if !n3! equ 3 echo,!s!-%%i
- endlocal&set "skip=skip=%p%"&goto :loop
- )
- )
- pause&exit
复制代码
作者: qixiaobin0715 时间: 2024-9-9 08:52
本帖最后由 qixiaobin0715 于 2024-9-9 09:29 编辑
实际上20、21楼的代码都是迭代法,20楼是逐行错位迭代。虽然在这里与15楼的“if到底”的要求不是太合辙,看样子迭代法是解决此类问题的其中一个捷径。
如果要用迭代法的话还是原贴中那位大佬代码更简洁,直接原地迭代:- set a1=!a2!
- set a2=!a3!
- ...
- set a9=!a10!
- set a10=%%b
- 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行文本就跳转感觉有点浪费,这样是否要节约些:- @echo off
- setlocal enabledelayedexpansion
- set /a n=n1=n2=n3=p=0
- :loop
- set /a p+=1
- setlocal
- for /f "%skip%tokens=1-2 delims=," %%i in (a.txt) do (
- set /a n+=1
- if %%j leq 6 (
- if !n! leq 3 set /a n1+=1
- if !n! equ 1 set "s=%%i"
- )
- if %%j geq 10 if !n! geq 4 if !n! leq 7 set /a n2+=1
- if %%j leq -2 if !n! geq 8 set /a n3+=1
- if !n! equ 10 (
- rem echo,!n1!,!n2!,!n3!
- if !n1! equ 3 if !n2! equ 4 if !n3! equ 3 echo,!s!-%%i
- )
- if !n! equ 10 set /a n=n1=n2=n3=p=0
- )
- endlocal
- set "skip=skip=%p%"
- if %p% lss 10 goto :loop
- 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楼代码相比要简单一些:- @echo off
- setlocal enabledelayedexpansion
- for /f "tokens=1* delims=," %%i in (a.txt) do (
- if %%j geq 10 (
- set a=!a!3
- ) else if %%j leq -2 (
- set a=!a!1
- if "!a:~-7!"=="3333111" (
- if not "!a:~9!"=="" (
- set b=!a:~,3!
- set b=!b:2=!
- if "!b:1=!"=="" (
- set /a n=%%i-10+1
- echo,!n!-%%i
- )
- )
- )
- ) else if %%j leq 6 (
- set a=!a!2
- ) else (
- set a=!a!4
- )
- set a=!a:~-9!
- )
- pause
复制代码
作者: qixiaobin0715 时间: 2024-9-11 14:32
简化一下楼上代码:- @echo off
- setlocal enabledelayedexpansion
- for /f "tokens=1* delims=," %%i in (a.txt) do (
- if %%j geq 10 (
- set a=!a!3
- ) else if %%j leq -2 (
- set a=!a!1
- if "!a:~-7!"=="3333111" (
- if "!a:2=1!"=="1113333111" (
- set /a n=%%i-10+1
- echo,!n!-%%i
- )
- )
- ) else if %%j leq 6 (
- set a=!a!2
- ) else (
- set a=!a!4
- )
- set a=!a:~-9!
- )
- pause
复制代码
欢迎光临 批处理之家 (http://bbs.bathome.net/) |
Powered by Discuz! 7.2 |