Board logo

标题: [文件操作] 批处理将文件以数字重命名 [打印本页]

作者: 随风    时间: 2008-6-9 17:13     标题: 批处理将文件以数字重命名

讨论:将文件以数字重命名
看似简单,其实不然。
现有a.txt文件内容如下,一行一个文件名。路径为当前目录。
要求:
   1、不能改变a.txt内容的顺序
   2、将当前目录下的所有jpg文件以序号的形式重命名 如:从1-16

   3、如果有16个文件,必须重命名为1-16,不允许出现16之后的序号

暂不公布我的代码,各位不防先试试。
a.txt 内容:
  1. 2.jpg
  2. 1.jpg
  3. a.jpg
  4. 5ww.jpg
  5. c.jpg
  6. f.jpg
  7. rty.jpg
  8. 3.jpg
  9. 11.jpg
  10. b.jpg
  11. 6.jpg
  12. e.jpg
  13. 8.jpg
  14. 111.jpg
  15. 7.jpg
  16. 30.jpg
复制代码


重新描述一下要求:
当前文件夹有一万多个jpg文件,文件名没有规律,有数字,英文,中文、及中英文混合。
要求:
   将jpg文件以数字形式重命名,必须是从1开始递增,即:最大的一个文件名就是文件的总数。
   要求效率,即:不能先判断文件的总数,再重命名。


[ 本帖最后由 随风 于 2008-6-10 23:55 编辑 ]
作者: namejm    时间: 2008-6-9 17:36

  没有看明白你的意思:是从a.txt中读取jpg文件名来重命名当前目录下的文件?a.txt只是一个单独的文件,如何有顺序一说?
作者: 随风    时间: 2008-6-9 17:46

a.txt中的内容其实就是当前文件夹下的jpg文件列表。
要求将当前文件夹里的所有jpg文件以序号的形式重命名。
但只能从 a.txt 获取当前文件夹里的所有 jpg 的文件名。
以序号重命名文件,陷阱重重,但如果用dir或for等命令来获取文件名的话,获取的先后次序会有一定规律,导致有些问题不能体现出来。
作者: namejm    时间: 2008-6-9 17:56

  随风 是担心重命名后文件名可能和现有文件名重名是吧?但是我始终没明白你"不能改变a.txt的顺序
"到底是什么意思:a.txt只是一个单独的文件,没看到它到底和谁排序呢?难道是不能改变a.txt文件内容的顺序?
作者: springcm    时间: 2008-6-9 19:46

不知道以下代码是不是投机:
  1. @echo on
  2. setlocal enabledelayedexpansion
  3. set n=0
  4. set n1=0
  5. for /f "tokens=*" %%a in (a.txt) do (
  6.      set /a n+=1
  7.      ren %%a t!n!.jpg
  8.     )
  9. :loop
  10. set /a n1+=1  
  11. ren t%n1%.jpg %n1%.jpg&&goto :loop
  12. exit
复制代码

作者: 随风    时间: 2008-6-9 20:37

呵呵,个人认为算投机。。
不过也不错,也是一个解决方法

[ 本帖最后由 随风 于 2008-6-11 16:53 编辑 ]
作者: wankoilz    时间: 2008-6-10 16:55

我有两个版本。第一个:
  1. @echo off
  2. for /f "delims=" %%i in (a.txt) do set/a n+=1
  3. for /f "delims=" %%i in (a.txt) do (
  4.   for /l %%j in (1,1,%n%) do if %%~ni equ %%j set .%%j=ok
  5. )
  6. for /f "delims=" %%i in (a.txt) do (
  7.   if not defined .%%~ni call :out %%i
  8. )
  9. pause
  10. :out
  11. for /l %%i in (1,1,%n%) do (if not defined .%%i (ren %1 %%i.jpg&set .%%i=ok&goto :eof))
复制代码
第二个更简单:
  1. @echo off
  2. for /f "delims=" %%i in (a.txt) do set/a n+=1
  3. for /f "delims=" %%i in (a.txt) do call :out %%i
  4. pause
  5. :out
  6. for /l %%i in (1,1,%n%) do (ren %1 %%i.jpg 2>nul&&goto :eof)
复制代码

作者: 随风    时间: 2008-6-10 17:15

呵呵,强免完成任务。
两个版本的效率都非常的低。。









..
作者: wankoilz    时间: 2008-6-10 17:21

暂时没想出很简洁的方法,再思考思考..........
作者: wankoilz    时间: 2008-6-10 21:06

再来一个,效率要比前两个要好:
  1. @echo off&setlocal enabledelayedexpansion
  2. for /f %%i in (a.txt) do (set/a n+=1&set .!n!=ok)
  3. for /f %%i in (a.txt) do (
  4.   if not defined .%%~ni (set/a n1+=1&set name!n1!=%%i
  5.   ) else (set .%%~ni=)
  6. )
  7. for /l %%i in (1,1,%n%) do (if defined .%%i (set/a n2+=1&set num!n2!=%%i))
  8. for /l %%i in (1,1,%n1%) do ren !name%%i! !num%%i!.jpg
复制代码

作者: 随风    时间: 2008-6-10 21:50

首先:效率仍是问题。
10 楼测试过吗?


代码绕的我好晕。。。

[ 本帖最后由 随风 于 2008-6-10 21:51 编辑 ]
作者: wankoilz    时间: 2008-6-10 23:27

10楼测试过,代码虽然多,但都是for和if,不过也只能说比前面的快点。测试了几次,平均耗时0.03秒。
思路是将a.txt中 范围数字 之外的名称装进一个数组,再将剩余a.txt中没用过的数字装进一个数组,再一一对应重命名。

[ 本帖最后由 wankoilz 于 2008-6-10 23:32 编辑 ]
作者: 随风    时间: 2008-6-10 23:55

见顶楼红色字部分,再试试。。。
作者: wankoilz    时间: 2008-6-11 00:15

测试1000个文件用了2.8秒,10000个不敢测试了。发现太多的set很耗时间........
再思考思考................

[ 本帖最后由 wankoilz 于 2008-6-11 00:32 编辑 ]
作者: lovelymorning    时间: 2008-6-11 16:07

想给想得太简单了,呵呵……

[ 本帖最后由 lovelymorning 于 2008-6-11 16:36 编辑 ]
作者: 随风    时间: 2008-6-11 16:27

呵呵,楼上是想简单了。
假设a.txt内容如下,也就是假设用dir得到的文件名顺序
a.jpg
1.jpg
2.jpg
你执行第一步后,把a.jpg改为1.jpg 就遇到的同名文件。

在你的例子中
ren "2.jpg" "1.jpg"
ren "1.jpg" "2.jpg"
把2改为1 第二句又把1改为了2  结果还是没有1.jpg
作者: wankoilz    时间: 2008-6-12 17:33

仍然没想出更高效率的方法,哪怕是直接ren 10000个文件,都要不少时间吧,难道还有批量命名的什么命令么................
作者: 梦想种子    时间: 2008-6-13 01:13

  1. @echo off
  2. setlocal enabledelayedexpansion
  3. for /f "delims=" %%i in (a.txt) do (
  4. set /a n+=1
  5. (ren !n!.jpg _!n!.jpg
  6. ren _%%i !n!.jpg||(ren %%i !n!.jpg)) 2>nul
  7. )
复制代码
如果文件名只含有中英数三种字符的话,这样就可以了吧。
作者: 随风    时间: 2008-6-13 02:34     标题: 18 楼

这个问题还真是绕人,看了半天,好像是没问题了。
加分。。。
作者: wankoilz    时间: 2008-6-13 10:57

我也再来一个。效率不如18楼,同样情况下测试2000个文件(1000个是范围内数字,1000个是字母),18楼的平均用3.4秒,我的用4秒半。但如果数字名称的文件很多的话,我的就比较有优势了,呵呵..
  1. @echo off
  2. for /f %%i in (a.txt) do (set/a max+=1)
  3. for /f %%i in (a.txt) do (
  4. call :out %%i
  5. )
  6. pause
  7. :out
  8. if %1 leq %max% goto :eof
  9. set /a n+=1
  10. if exist %n%.jpg (goto :out
  11. ) else (ren %1 %n%.jpg)
复制代码

[ 本帖最后由 wankoilz 于 2008-6-15 20:18 编辑 ]
作者: 随风    时间: 2008-6-13 13:23

wankoilz 兄弟的钻研精神真是可嘉!
不错,
作者: more    时间: 2008-6-15 12:30

个人认为5楼和18楼实现了改名的操作,但是并不以a.txt的内容作为参考(不合楼主要求),导致了文件名和原文件对不上号,不可取
20楼的代码经测试不成功,而且也不符合不得判断文件总数的要求
期待中...............
作者: 随风    时间: 2008-6-15 13:28     标题: 回22楼

可能我没说清楚,要求是只要把文件按数序号重命名就可以了的,不用管文件名和原文件对不对的上号,所以5楼和18楼应该是可以的。
当然最理想的应该是不需要重命名的文件就不重命名。
比如
a.jpg
5.jpg
2.jpg
c.jpg
其中的2.jpg就不需要重命名。
作者: 梦想种子    时间: 2008-6-15 14:21     标题: 回复 22楼 的帖子

用这个BAT生成JPG:
  1. @echo off
  2. setlocal enabledelayedexpansion
  3. set n=0
  4. del /q *.jpg
  5. for /f "delims=" %%i in (a.txt) do (
  6. set /a n+=1
  7. echo !n!>%%i
  8. )
  9. pause
复制代码
这样每个JPG文件内容中都会有一个数字,是按照a.txt中文件名排列的序号。

然后执行重命名的BAT,就可以检查是否对号命名了(若是,改后文件名与该JPG里的数字相同)。

经逐一检查,5楼和18楼的都能严格按照a.txt中的文件名排序对号命名的。

[ 本帖最后由 梦想种子 于 2008-6-15 14:25 编辑 ]
作者: more    时间: 2008-6-15 15:13

原帖由 随风 于 2008-6-15 13:28 发表
可能我没说清楚,要求是只要把文件按数序号重命名就可以了的,不用管文件名和原文件对不对的上号,所以5楼和18楼应该是可以的。
当然最理想的应该是不需要重命名的文件就不重命名。
比如
a.jpg
5.jpg
2.jpg
...

如果是这样的话,我也可以,而且还不会把已经存在的文件(序号小于16的文件)重命名:
  1. @echo off
  2. for /f "delims=" %%i in (a.txt) do set /a m+=1
  3. for /f "delims=" %%i in (a.txt) do call :ren_ %%i
  4. goto :eof
  5. :ren_
  6. if %~n1 leq %m% goto :eof
  7. :again
  8. set /a n+=1
  9. if exist %n%.jpg goto :again
  10. ren %1 %n%.jpg
  11. goto :eof
复制代码
用这个BAT生成JPG:复制内容到剪贴板代码:
@echo off
setlocal enabledelayedexpansion
set n=0
del /q *.jpg
for /f "delims=" %%i in (a.txt) do (
set /a n+=1
echo !n!>%%i
)
pause这样每个JPG文件内容中都会有一个数字,是按照a.txt中文件名排列的序号。

然后执行重命名的BAT,就可以检查是否对号命名了(若是,改后文件名与该JPG里的数字相同)。

经逐一检查,5楼和18楼的都能严格按照a.txt中的文件名排序对号命名的。

我测试的结果却完全不相同,你真的检查过了吗????????????

[ 本帖最后由 more 于 2008-6-15 15:21 编辑 ]
作者: 梦想种子    时间: 2008-6-15 15:29     标题: 回 25 楼

我测试的结果却完全不相同,你真的检查过了吗????????????
  1. @echo off
  2. setlocal enabledelayedexpansion
  3. for /f "delims=" %%i in ('dir /b *.jpg') do (
  4. set /p t=<%%i
  5. set /p=!t! %%~ni <nul
  6. if !t! == %%~ni (echo Yes) else echo No
  7. )
  8. pause
复制代码
本来是手工检查的,没有错。
后来再写了个BAT,检查依然无误...

我环境是WIN XP PRO + SP2
作者: more    时间: 2008-6-15 16:16     标题: 回26楼

我指的是文件里的内容已经改变了,运行以下代码就知道了
  1. @echo off
  2. setlocal enabledelayedexpansion
  3. del /f/q *.jpg
  4. ::按a.txt的内容生成固定内容的.jpg文件(24楼)
  5. for /f "delims=" %%i in (a.txt) do (
  6. set /a n+=1
  7. echo !n!>%%i
  8. )
  9. ::显示.jpg文件里的内容,作验证用
  10. echo 以下为更名前的文件及对应的内容
  11. for /f "delims=" %%a in ('type a.txt') do (set/p=%%a     <nul&type %%a)
  12. pause
  13. ::以下为18楼的重命名代码
  14. echo.&echo 以下为18楼的代码更名后的文件及对应的内容&echo.
  15. set n=0
  16. for /f "delims=" %%i in (a.txt) do (
  17. set /a n+=1
  18. (ren !n!.jpg _!n!.jpg
  19. ren _%%i !n!.jpg||(ren %%i !n!.jpg)) 2>nul
  20. )
  21. ::以下为验证代码
  22. for /l %%a in (1 1 16) do (
  23.    set /p=%%a.jpg     <nul&type %%a.jpg
  24. )
  25. pause
复制代码

作者: more    时间: 2008-6-15 16:28

下面的是我的重命名代码,作一下对比就清楚了:
  1. @echo off
  2. setlocal enabledelayedexpansion
  3. del /f/q *.jpg
  4. ::按a.txt的内容生成固定内容的.jpg文件(24楼)
  5. for /f "delims=" %%i in (a.txt) do (
  6. set /a n+=1
  7. echo !n!>%%i
  8. )
  9. ::显示.jpg文件里的内容,作验证用
  10. echo 以下为更名前的文件及对应的内容
  11. for /f "delims=" %%a in ('type a.txt') do (set/p=%%a     <nul&type %%a)
  12. set n=0
  13. echo.&echo 以下为更名后的文件及对应的内容&echo.
  14. for /f "delims=" %%i in (a.txt) do set /a m+=1
  15. for /f "delims=" %%i in (a.txt) do call :ren_ %%i
  16. goto :count_
  17. :ren_
  18. if %~n1 leq %m% goto :eof
  19. :again
  20. set /a n+=1
  21. if exist %n%.jpg goto :again
  22. ren %1 %n%.jpg
  23. goto :eof
  24. :count_
  25. for /l %%a in (1 1 16) do (
  26.    set /p=%%a.jpg     <nul&type %%a.jpg
  27. )
  28. pause
复制代码

作者: 梦想种子    时间: 2008-6-15 16:32     标题: 回复 27楼 的帖子

我运行的结果是这个:

以下为更名前的文件及对应的内容
2.jpg     1
1.jpg     2
a.jpg     3
5ww.jpg     4
c.jpg     5
f.jpg     6
rty.jpg     7
3.jpg     8
11.jpg     9
b.jpg     10
6.jpg     11
e.jpg     12
8.jpg     13
111.jpg     14
7.jpg     15
30.jpg     16
请按任意键继续. . .

以下为18楼的代码更名后的文件及对应的内容

1.jpg     1
2.jpg     2
3.jpg     3
4.jpg     4
5.jpg     5
6.jpg     6
7.jpg     7
8.jpg     8
9.jpg     9
10.jpg     10
11.jpg     11
12.jpg     12
13.jpg     13
14.jpg     14
15.jpg     15
16.jpg     16
请按任意键继续. . .

证明18楼代码没有问题。

我再把代码换成5楼的,结果还是上面的结果。所以5楼代码没有错。
究竟是怎么回事?有没有第三个人试试?
作者: more    时间: 2008-6-15 16:40     标题: 回29楼

更名前的内容和更名后的内容已经改变啦!
                         更名前           更名后
1.jpg                    2                               1
2.jpg                    1                               2
3.jpg                    8                               3
............

[ 本帖最后由 more 于 2008-6-15 16:47 编辑 ]
作者: 梦想种子    时间: 2008-6-15 16:55

这肯定要变的啊...

按照a.txt的顺序:

2.jpg 要改成 1.jpg
1.jpg 要改成 2.jpg
a.jpg 要改成 3.jpg
5ww.jpg 要改成 4.jpg
....

注意,原来的2.jpg不同现在的2.jpg了,因为根据a.txt,要改成1.jpg...依此类推
所以,结果就是对的了。不是么?
作者: 随风    时间: 2008-6-15 16:58

好热闹,
我来说两句。
其实我们把a.txt的内容加上行号就可以很好的说明问题了
其实 梦想种子 的意思就是以行号重命名文件,18楼的代码也确实达到如此功效。
而more的意思好像是:
 以16个文件为例
  若有2.jpg则不能重命名2.jpg ..........
    若有10.jpg则不能重命名10.jpg ..........
    .....................
个人认为这种思路是最理想的。
作者: more    时间: 2008-6-15 17:17

好热闹,
我来说两句。
其实我们把a.txt的内容加上行号就可以很好的说明问题了
其实 梦想种子 的意思就是以行号重命名文件,18楼的代码也确实达到如此功效。
而more的意思好像是:
 以16个文件为例
  若有2.jpg则不能重命名2.jpg ..........
    若有10.jpg则不能重命名10.jpg ..........
    .....................
个人认为这种思路是最理想的。


是的,我以为楼主的原意是这样的(虽然并不是),不过我的代码可达到了这个效果喔.
作者: 随风    时间: 2008-6-15 18:47     标题: 33楼

呵呵。但是你的代码统计了文件总数,同样不合题意啊。
作者: wankoilz    时间: 2008-6-15 20:21

我的有错误,改正了,不过以前的测试文件比较规则,所以可以运行。思路是和more的一样。
作者: more    时间: 2008-6-15 20:22

哈哈,如果没有23楼的回复,我也不会贴出25楼的代码的,所以啊,正如我在22楼所说的,还没有符合题意的代码,依然在期待中........................
作者: 梦想种子    时间: 2008-6-15 21:53

  1. @echo off
  2. setlocal enabledelayedexpansion
  3. for /f "delims=" %%i in (a.txt) do (
  4. set /a n+=1
  5. call :check "%%i"
  6. )
  7. pause&exit
  8. :check
  9. if defined %~n1 (set /a n-=1&goto :eof)
  10. if exist !n!.jpg (
  11. set !n!=OK
  12. set /a n+=1
  13. goto check
  14. ) else (
  15. ren %1 !n!.jpg
  16. )
复制代码

作者: 随风    时间: 2008-6-15 22:03

哈哈哈哈,37楼 和我的代码一模一样了。
哈哈。。。。
  1. @echo off
  2. for /f "delims=" %%a in (a.txt) do call :loop "%%a"
  3. pause
  4. :loop
  5. set /a n+=1
  6. if exist "%n%.jpg" set .%n%=a&goto loop
  7. if not defined .%~n1 ren "%~1" "%n%.jpg"&set .%n%=a
  8. goto :eof
复制代码

作者: 梦想种子    时间: 2008-6-15 22:49     标题: 回复 38楼 的帖子

你逻辑顺序比较好,所以简短很多。
作者: more    时间: 2008-6-15 23:27

经测试37楼成功,38楼不成功,原因如下:
这是a.txt的部分内容:
2.jpg
1.jpg
a.jpg
5ww.jpg
c.jpg
当call :loop 2.jpg;当n加到4的时候出错,
if exist "4.jpg" set .4=a&goto loop   ==>这句不执行
if not defined .2 ren "%~1" "4.jpg"&set .4=a    ==>这句也不执行
goto :eof    ==>一直未定义.4
所以出错
作者: 随风    时间: 2008-6-15 23:38

是啊,漏了一句。else set /a n-=1
:
  1. @echo off
  2. for /f "delims=" %%a in (a.txt) do call :loop "%%a"
  3. pause
  4. :loop
  5. set /a n+=1
  6. if exist "%n%.jpg" set .%n%=a&goto loop
  7. if not defined .%~n1 (ren "%~1" "%n%.jpg"&set .%n%=a) else set /a n-=1
  8. goto :eof
复制代码





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