Board logo

标题: [文件操作] [已解决]批处理如何批量重命名文件? [打印本页]

作者: tsys    时间: 2011-5-30 18:41     标题: [已解决]批处理如何批量重命名文件?

本帖最后由 tsys 于 2011-5-30 23:25 编辑

我使用dir G:\*.jpg /b /s >a.txt 把G盘所有子目录的jpg文件全部获取了,基本上每个子目录都只有一个jpg文件,想要将所有不同子目录的jpg文件全部重名为xbs.jpg。如果子目录内存在3个图片,想要改为xbs.jpg,xbs1.jpg,xbs2.jpg.请问代码该如何写?
作者: 我是马甲    时间: 2011-5-30 19:29

  1. @echo off&set cd=%cd%
  2. for /f "delims=" %%i in ('dir/b/s *.jpg') do (
  3.     if exist "%%i" (
  4.         if exist "%%~dpixbs.jpg" (
  5.             cd/d %%~dpi
  6.             set /a n=0
  7.             for /f "delims=" %%j in ('dir/b *.jpg') do (
  8.                 set var=%%~nxj&set /a n+=1
  9.                 setlocal enabledelayedexpansion
  10.                 if not "!var!"=="xbs.jpg" (
  11.                    ren "!var!" "xbs!n!.jpg"
  12.                 ) else (set /a n-=1)
  13.                 for %%k in (!n!) do endlocal&set n=%%k
  14.             )
  15.             cd/d %cd%
  16.            ) else (ren "%%i" "xbs.jpg")
  17.      )
  18. )
  19. pause
复制代码

作者: 601997526    时间: 2011-5-30 21:20

  1. @echo off&setlocal ENABLEDELAYEDEXPANSION
  2. for /r %%i in (*.jpg) do call :x %%~fsi&set a=
  3. pause&exit
  4. :x
  5. ren %1 xbs!a!.jpg 2>nul||(set /a a+=1&goto :x)
复制代码

作者: tmplinshi    时间: 2011-5-30 21:20

本帖最后由 tmplinshi 于 2011-5-31 00:18 编辑
  1. @echo off
  2. SetLocal
  3. set "prefix=xbs"
  4. set "_cd=%cd%"
  5. for /f "usebackq delims=" %%a in ("a.txt") do (
  6.     set path_now=%%~dpa
  7.     SetLocal EnableDelayedExpansion
  8.     if /i "!path_now!" neq "!path_last!" (
  9.         EndLocal
  10.         set path_last=%%~dpa
  11.         set n=
  12.         cd /d %%~dpa
  13.         if exist "%prefix%*.jpg" ren "%prefix%*.jpg" "*.*.jpg"
  14.         for /f "delims=" %%i in (' dir /b "*.jpg" ') do (
  15.             set file=%%i
  16.             SetLocal EnableDelayedExpansion
  17.             ren "!file!" "!prefix!!n!.jpg"
  18.             EndLocal
  19.             set /a n += 1
  20.         )
  21.     ) else EndLocal
  22. )
  23. cd /d "%_cd%"
复制代码

作者: 601997526    时间: 2011-5-30 21:24

不是吧,这个需要那么复杂吗
作者: 随风    时间: 2011-5-30 21:48

5# 601997526

用call 效率太低
开变量延迟又要考虑文件名含半角!号的情况。
作者: tmplinshi    时间: 2011-5-30 22:15

本帖最后由 tmplinshi 于 2011-5-31 08:10 编辑

5# 601997526

写那么复杂,主要考虑了两点:

1. 考虑了半角 ! 号。
2. call 的效率低。
      用好几个 for 都比一个 call 的速度快。call 的次数很多时,速度差异特别明显。

你的代码有两个会出错的地方:

1. for /r 会造成文件被重命名多次(测试环境:Windows XP SP2)
(之前没仔细看,你的代码虽然造成了文件被重命名多次,不过最终结果并不会出错。)

测试代码:
  1. @echo off
  2. SetLocal EnableDelayedExpansion
  3. for /r %%a in (*.jpg) do (
  4.     set /a n += 1
  5.     echo "%%~nxa" → "!n!.jpg"
  6.     ren "%%a" "!n!.jpg"
  7. )
  8. pause
复制代码
文件夹内只有“1 2.jpg”和“3 4.jpg”两个文件。运行结果:
"3 4.jpg" → "1.jpg"
"1 2.jpg" → "2.jpg"
"1.jpg" → "3.jpg"
"2.jpg" → "4.jpg"

请按任意键继续. . .

文件被重命名了两次。这种错误发生在文件名含有空格时。(补充:短名与原名不同时也会被重命名多次)

2. call :x %%~fsi
如果路径中含有符号“&”,且没有空格,例如“c:\1&2\3.txt”,这个路径的短名还是“c:\1&2\3.txt”。
作者: tsys    时间: 2011-5-30 22:23

2# 我是马甲


谢谢,能否解释下每句的用途呢?
作者: CrLf    时间: 2011-5-30 22:38

本帖最后由 zm900612 于 2011-5-31 12:22 编辑

8# tsys


替他解释的:
  1. @echo off&set cd=%cd%
  2. ::关闭回显,并将cd变量设置为固定值
  3. for /f "delims=" %%i in ('dir/b/s *.jpg') do (
  4. rem 获取“鸡屁股”文件列表
  5.     if exist "%%i" (
  6.     rem 如果存在该文件则
  7.         if exist "%%~dpixbs.jpg" (
  8.         rem 如果同路径下存在xbs.鸡屁股文件,则
  9.             cd/d %%~dpi
  10.             rem 切换到其目录下(建议改成pushd和popd,可以简化操作)
  11.             set /a n=0
  12.             rem 设置变量n为0,小建议,不使用/a开关效率更高
  13.             for /f "delims=" %%j in ('dir/b *.jpg') do (
  14.             rem 获取所切换的目录下的jpg文件列表
  15.                 set var=%%~nxj&set /a n+=1
  16.                 rem 设置变量var值为所获取的文件名,并将n加1
  17.                 setlocal enabledelayedexpansion
  18.                 rem 打开变量延迟(一看就是老手)
  19.                 if not "!var!"=="xbs.jpg" (
  20.                 rem 如果该文件不叫作xbs.jpg
  21.                    ren "!var!" "xbs!n!.jpg"
  22.                    rem 则将该文件改名为xbs%n%.jpg,此时n位于语块之内,所以要使用有变量延迟效果的!n!
  23.                 ) else (set /a n-=1)
  24.                 rem 否则让n减1
  25.                 for %%k in (!n!) do endlocal&set n=%%k
  26.                 rem 与setlocal对应,关闭回显,并将会在退出堆栈的过程中丢失的变量n保留
  27.             )
  28.          cd/d %cd%
  29.          rem 回到原始位置
  30.          ) else (ren "%%i" "xbs.jpg")
  31.          rem 否则(对应第二层的if)将文件改名为xbs.jpg
  32.     )
  33. )
  34. pause
复制代码

作者: 601997526    时间: 2011-5-30 23:35

7# tmplinshi
晕,这个我不是没有排错吗,至于吗,加两判断下不就行了,至于速度到确实是个问题
作者: tmplinshi    时间: 2011-5-31 08:47

本帖最后由 tmplinshi 于 2011-5-31 08:55 编辑

10# 601997526

我只是回答了你的疑问“需要那么复杂吗”。顺便指出你代码中可能出现的错误。如有言语不妥的地方,请见谅
作者: dennis1314    时间: 2011-5-31 09:49

这个果然经典,看完例子还是有点不明白
作者: 随风    时间: 2011-5-31 13:09

可以更简单高效
  1. @echo off
  2. for /f "delims=" %%i in ('dir/b/s *.jpg') do (
  3.     set str=%%~dpi&set str2=%%~nxi
  4.     setlocal enabledelayedexpansion
  5.     if not "!str!"=="!num!" (set n=) else set /a n+=1
  6.     ren "!str!!str2!" "xbs!n!.jpg"
  7.     for %%a in (!n!) do endlocal&set n=%%a
  8.     set "num=%%~dpi"
  9. )
  10. pause
复制代码

作者: tmplinshi    时间: 2011-5-31 15:32

13# 随风


如果一个文件夹内有下列文件...
1.jpg
2.jpg
3.jpg
xbs.jpg
xbs1.jpg
作者: 随风    时间: 2011-5-31 16:17

14# tmplinshi

多谢指出,确实没考虑到重名文件的问题,已修改如下。
  1. @echo off
  2. for /f "delims=" %%i in ('dir/b/s *.jpg') do (
  3.     set str=%%~dpi&set str2=%%~nxi
  4.     setlocal enabledelayedexpansion
  5.     if not "!str!"=="!num!" (
  6.         set "n="
  7.         ren "!str!*.jpg" "*.*.jpg"
  8.     ) else set /a n+=1
  9.     ren "!str!!str2!.jpg" "xbs!n!.jpg"
  10.     for %%a in (!n!) do endlocal&set n=%%a
  11.     set "num=%%~dpi"
  12. )
  13. pause
复制代码





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