中国DOS联盟

-- 联合DOS 推动DOS 发展DOS --

联盟域名:www.cn-dos.net 论坛域名:www.cn-dos.net/forum
DOS,代表着自由开放与发展,我们努力起来,学习FreeDOS和Linux的自由开放与GNU精神,共同创造和发展美好的自由与GNU GPL世界吧!

中国DOS联盟论坛
现在时间是 2026-06-14 19:03
中国DOS联盟论坛 » DOS批处理 & 脚本技术(批处理室) » 已结:[转帖求助]一个批量命名的批处理
楼 主 已结:[转帖求助]一个批量命名的批处理 发表于 2005-12-05 23:19 ·  中国 重庆 联通
高级用户
★★
积分 772
发帖 273
注册 2004-10-23 00:00
UID 32861
性别 男
状态 离线
昨晚我在中国电脑俱乐部看到了一个和批处理有关的问题
作者的原话如下:
求一个关于文件批量改名简单的程序(在线等)
情况是这样的:我现在工作需要处理些图片,把图片分类放在许多文件夹里,然后在把每个文件夹里的图片加序号改名,比如一个文件夹名字为AAA111,里面有3个图片,就要把这3图片名字改为AAA111-01,AAA111-02,AAA111-03.我想大致就是把文件名提取,然后在.......真后悔读书的时候没好好掌握一门语言,哎~
前些天图片数量少,我用个更名软件还能应付,最近每天4,5千张,实在是弄不了了,路过的朋友帮帮忙撒.我QQ7885347

当时我也想用批处理解决但是一下想不到怎么提取目录名
就用VBS写了一个
代码如下:
Const ForReading = 1, ForWriting = 2, ForAppending = 8
Const TristateUseDefault = -2, TristateTrue = -1, TristateFalse = 0
const WindowsFolder=0,SystemFolder=1,TemporaryFolder=2
Set fs = CreateObject("Scripting.FileSystemObject")
Set ws = CreateObject("Wscript.Shell")
set sys = fs.GetSpecialFolder(SystemFolder)
sum = 0
call input()
private sub input()
dim str
str=InputBox( "请输入你要搜索的路径,程序" & vbnewline & "会搜索指定路径的所有子路径","目标目录")
if str <> "" then
if fs.FolderExists(str) then
call search(str)
else
Msgbox "请输入正确的路径",0,"提示"
call input
end if
else
if msgbox(" 您确定退出本程序吗?",4,"提示")=vbyes then wscript.quit
call input
end if
end sub

Function search(path1)
dim f1,f2,subfolder,path2,path2file,path2files,renname,foldername,appfile,appfiles,i,j,appfilename,appfilesname
if right(path1,1) <> "\" then path1 = path1 & "\"
Set f = fs.GetFolder(path1)
set appfiles = f.files
for each appfile in appfiles
appfilename = path1 & appfile.name
For j = Len(f) To 1 Step -1 '这里至关重要
If InStr("\", Mid(f, j, 1)) Then Exit For
Next
appfilesname = Mid(f, j + 1, Len(f) - j) '分离出目录名
if Lcase(fs.GetExtensionName(appfilename)) = "jpg" or Lcase(fs.GetExtensionName(appfilename)) = "bmp" then
ws.run "cmd /c ren " & appfilename & " " & appfilesname & fs.GetBaseName(appfilename) & "-" & sum & "." &
fs.GetExtensionName(appfilename),0,true
sum = sum + 1
end if
next
sum = 0
Set sf = f.SubFolders

For Each f1 in sf
f2 = path1 & f1.name & "\"
set path2 = fs.getfolder(f2)
set path2file = path2.files
for each path2files in path2file
renname = f2 & path2files.name
foldername = fs.GetParentFolderName(renname)
For i = Len(foldername) To 1 Step -1
If InStr("\", Mid(foldername, i, 1)) Then Exit For
Next
foldername = Mid(foldername, i + 1, Len(foldername) - i)
if Lcase(fs.GetExtensionName(renname)) = "jpg" or Lcase(fs.GetExtensionName(renname)) = "bmp" then
ws.run "cmd /c ren " & renname & " " & foldername & fs.GetBaseName(renname) & "-" & sum & "." & fs.GetExtensionName(renname),0,true
sum = sum + 1
end if
next
sum = 0
search(f2)
next

End Function

msgbox "完成操作",0,"提示"

谁能给出批处理代码:

[ Last edited by willsort on 2005-12-9 at 16:09 ]
http://www.msfans.net/bbs/
2 提个思路: 发表于 2005-12-05 23:34 ·  中国 重庆 云阳县 电信
银牌会员
★★★
积分 2,165
发帖 730
注册 2004-04-21 00:00
UID 22966
性别 男
状态 离线
dir/a:d /b 〉定向到列表文件
然后再用作批处理参数……
3 发表于 2005-12-06 11:46 ·  中国 辽宁 锦州 中移铁通
荣誉版主
★★★
积分 1,338
发帖 356
注册 2005-07-15 12:09
UID 40733
性别 男
状态 离线
用 Total Commander 很方便的,命名规则处填 [P][C] 就完事了。当然用批处理也不是不可完成,但是确实有这个必要吗?
提取目录名可以试试
for /r %i in (.) do @echo %~ni
  ☆开始\运行 (WIN+R)☆
%ComSpec% /cset,=何奈无── 。何奈可无是原,事奈无做人奈无&for,/l,%i,in,(22,-1,0)do,@call,set/p= %,:~%i,1%<nul&ping/n 1 127.1>nul

4 发表于 2005-12-06 16:04 ·  中国 重庆 巴南区 电信
高级用户
★★
积分 772
发帖 273
注册 2004-10-23 00:00
UID 32861
性别 男
状态 离线
Originally posted by bush at 2005-12-5 11:34 PM:
dir/a:d /b 〉定向到列表文件
然后再用作批处理参数……


有必要啊~
使用批处理简单方便些
只是对于SUM的递加和换了目录又重新开始递加不是那么好实现吧
http://www.msfans.net/bbs/
5 发表于 2005-12-06 17:19 ·  中国 辽宁 锦州 中移铁通
荣誉版主
★★★
积分 1,338
发帖 356
注册 2005-07-15 12:09
UID 40733
性别 男
状态 离线
我仍然认为专业的重命名和文件管理软件来做这件事最合适,而用批处理完成这个任务对于批处理不熟悉的人来说无疑增加使用难度。

既然有必要就给你写一个,只作为技术讨论。

:: xrename.cmd -- 按序号重命名文件,并将目录名添加到文件名前。
:: by: 无奈何 - 2005-12-6 - 联系:wunaihe@gmail.com - 环境: NT 以上
@echo off
for /r %%i in (.) do (
set n=1000
pushd "%%i"
for /f "delims=" %%a in ('dir /b *.jpg 2^>nul') do (
set /a n+=1
call :rname "%%~ni" "%%~nxa" "%%n:~1%%"
)
popd
)
goto :EOF
:rname
ren %2 %1-%3%~x2
goto :EOF

我没有做细节处理,命名格式为 3 位数字,默认只重命名 jpg 文件,漠视重命名失败。有必要自行添加修改。
  ☆开始\运行 (WIN+R)☆
%ComSpec% /cset,=何奈无── 。何奈可无是原,事奈无做人奈无&for,/l,%i,in,(22,-1,0)do,@call,set/p= %,:~%i,1%<nul&ping/n 1 127.1>nul

6 发表于 2005-12-06 19:33 ·  中国 重庆 联通
高级用户
★★
积分 772
发帖 273
注册 2004-10-23 00:00
UID 32861
性别 男
状态 离线
确实高明~~
http://www.msfans.net/bbs/
7 发表于 2005-12-07 21:08 ·  中国 山西 临汾 中移铁通
元老会员
★★★★
Batchinger
积分 4,432
发帖 1,512
注册 2002-10-18 00:00
UID 19
性别 男
状态 离线
Re 无奈何:

没有实际测试这段代码,仅仅纸上谈兵提几点建议:

1、可否在 for /f 中加上文件的路径,以避免 pushd/popd 的使用?
2、可否将 for /f 改为 for %%a in (files) 的形式?
3、可否使用 setlocal 启动变量延迟,以避免 call :rname?
4、如果需要使用 call ,那么可否不用传递变量n,而在 :rname 中直接引用?
※ Batchinger 致 Bat Fans:请访问 批处理编程的异类 ,欢迎交流与共享批处理编程心得!
8 发表于 2005-12-08 13:50 ·  中国 辽宁 锦州 中移铁通
荣誉版主
★★★
积分 1,338
发帖 356
注册 2005-07-15 12:09
UID 40733
性别 男
状态 离线
for /f "delims=" %%a in ('dir /b *.jpg 2^>nul') do (

to willsort
兄的几点建议真是点点击中要害,实在是比我高明多了。由于写批程序时总是不自觉的向曾经写过的程序片段靠拢,哪怕是有更简洁处理方式也想不到了,看来习惯思维太绊脚了。关于第二点 for /f 也有一点好处,就是可以利用其后 dir /o 参数来定义文件重命名顺序,来增强应用的灵活性,只是在本例无此要求,所以也就无意义了。
修改一下,缩水不少。

@echo off
setlocal ENABLEDELAYEDEXPANSION
for /r %%i in (.) do (
set n=1000
for %%a in ("%%i\*.jpg") do (
set /a n+=1
ren "%%i\%%a" "%%~ni"-!n:~1!%%~xa
)
)
goto :EOF


上面的是原贴内容,本来已经完结,zreo 发现有问题并通知了我,居然存在严重 bug 。我仔细研究了一下找到了原因,这同时也是一个有趣的问题,所以我不直接修改原程序了,简单叙述一下这个问题。
请注意一下上面代码红色的部分,我本想省去 for /f 繁琐的命令输出解析,而直接用 for 获取文件名。但这就成了问题的根源,for %%a ... 会获取已经重命名后的文件而再次命名,文件数量多时会造成一直重命名的死循环。所以仍旧采用原先的处理方式,修正如下:


  1. :: xrename.cmd -- 按序号重命名文件,并将目录名添加到文件名前。
  2. rem 2005-12-12 修正并着色
  3. @echo off
  4. setlocal ENABLEDELAYEDEXPANSION
  5. for /r %%i in (.) do (
  6. set n=1000
  7. for /f "delims=" %%a in (' dir /b "%%i\*.jpg" 2^>nul ') do (
  8. set /a n+=1
  9. ren "%%i\%%a" "%%~ni"-!n:~1!%%~xa
  10. )
  11. )
  12. goto :EOF



[ Last edited by 无奈何 on 2005-12-12 at 21:59 ]
  ☆开始\运行 (WIN+R)☆
%ComSpec% /cset,=何奈无── 。何奈可无是原,事奈无做人奈无&for,/l,%i,in,(22,-1,0)do,@call,set/p= %,:~%i,1%<nul&ping/n 1 127.1>nul

9 发表于 2005-12-12 02:03 ·  中国 辽宁 锦州 中移铁通
荣誉版主
★★★
积分 1,338
发帖 356
注册 2005-07-15 12:09
UID 40733
性别 男
状态 离线
to zreo
你的问题让我发现一个重大 bug ,已经修正了。
  ☆开始\运行 (WIN+R)☆
%ComSpec% /cset,=何奈无── 。何奈可无是原,事奈无做人奈无&for,/l,%i,in,(22,-1,0)do,@call,set/p= %,:~%i,1%<nul&ping/n 1 127.1>nul

10 发表于 2005-12-12 11:24 ·  中国 福建 泉州 电信
初级用户
积分 51
发帖 14
注册 2005-11-06 20:02
UID 44706
性别 男
状态 离线
for /F "delims=" %a in ('dir /b *.jpg 2>nul')
这个得不到答案,而且还不能给文件重命名,用了一个得出来的结果是这样的。
I:\>(
set n=1000
for /F "delims=" %a in ('dir /b *.jpg 2>nul') do (
set /a n+=1
ren "%a" "图片"-!n:~1!%~xa

在我的机上试了一下,%a得不到文件参数,这样就不能给文件重命名了

echo on
setlocal ENABLEDELAYEDEXPANSION
for /r %%i in (.) do (
set n=1000
pushd "%%i"
for /f "delims=" %%a in ('dir /b *.jpg 2^>nul') do (
set /a n+=1
ren "%%a" "%%~ni"-!n:~1!%%~xa
)
)
goto :EOF


加了一个pushd "%%i"就得到值了。可以解释一下吗?

[ Last edited by zreo on 2005-12-12 at 11:38 ]
11 发表于 2005-12-12 11:37 ·  中国 辽宁 锦州 中移铁通
荣誉版主
★★★
积分 1,338
发帖 356
注册 2005-07-15 12:09
UID 40733
性别 男
状态 离线
to zreo
在批处理文件中要用 %% 替换 % 。
  ☆开始\运行 (WIN+R)☆
%ComSpec% /cset,=何奈无── 。何奈可无是原,事奈无做人奈无&for,/l,%i,in,(22,-1,0)do,@call,set/p= %,:~%i,1%<nul&ping/n 1 127.1>nul

12 发表于 2005-12-12 11:40 ·  中国 福建 泉州 电信
初级用户
积分 51
发帖 14
注册 2005-11-06 20:02
UID 44706
性别 男
状态 离线
我在批处理中是用双%%号的,可是%a还是得不到参数,反面加了一句
pushd "%%i"
就可以得到相要的了。
13 发表于 2005-12-12 14:04 ·  中国 辽宁 锦州 中移铁通
荣誉版主
★★★
积分 1,338
发帖 356
注册 2005-07-15 12:09
UID 40733
性别 男
状态 离线
pushd "%%i" 更改了当前路径,然后对当前目录下文件进行更名。
可以用全路径,省去这条语句,我又改了一下。
  ☆开始\运行 (WIN+R)☆
%ComSpec% /cset,=何奈无── 。何奈可无是原,事奈无做人奈无&for,/l,%i,in,(22,-1,0)do,@call,set/p= %,:~%i,1%<nul&ping/n 1 127.1>nul

论坛跳转: