Board logo

标题: [文本处理] 【已解决】批处理怎样按一定规则重命名文件(包含子文件夹)? [打印本页]

作者: ZeronoFreya    时间: 2014-5-3 15:25     标题: 【已解决】批处理怎样按一定规则重命名文件(包含子文件夹)?

如题,某   文件夹A     下含有
                                                                      ***[01]***.txt   
                                                                      ***[02]***.txt   
                                                                      ***[03]***.txt   
                                                                          ......
如此命名规则的文件,将文件夹A   拖放到   批处理X  ,

文件重命名为
                                                                     01.txt   
                                                                     02.txt   
                                                                     03.txt   
                                                                       ......
请各位前辈赐教!

(ps.  曾经找到过一段vbs脚本,能达成要求,但必须要复制到文件夹根目录才行,而且,当出现01.MP4时,会重命名为01.txt.txt,很郁闷
  1. Set FSO = CreateObject("Scripting.FileSystemObject")
  2. For Each File in FSO.GetFolder(".").Files
  3.    Ext = FSO.GetExtensionName(File)
  4.    If LCase(Ext) = "txt" Or LCase(Ext) = "doc" Or LCase(Ext) = "ass" Then RenFiles
  5. Next
  6. MsgBox "OK"
  7. Sub RenFiles()
  8.    Set Re = New RegExp
  9.    Re.Pattern = "(^.*\[)(\d{2})(\].*$)"
  10.    Re.Global = True
  11.    File.Name = Re.Replace(File.Name,"$2") & "." & Ext
  12. End Sub
复制代码

嗯,感谢各位的帮助,经过各种各样的过程,总之我已经得到满意结果了,再此感谢给位前辈的不吝赐教!

感谢大家的帮助!!!!
作者: 522235677    时间: 2014-5-3 17:05

本帖最后由 522235677 于 2014-5-3 17:06 编辑
  1. @echo off
  2. for /f "delims=" %%a in ('dir /b "%~1"') do (
  3.   for /f "tokens=2 delims=[]" %%b in ("%%~nxa") do echo ren "%~1\%%a" "%%b%%~xa"
  4. )
  5. pause
复制代码
先测试,然后去掉echo
作者: ZeronoFreya    时间: 2014-5-3 18:01

回复 2# 522235677

嗯,有点问题,运行后结果如下:
    [qzgu][Escha&LogynoAtelier~][01][CB].txt

     Escha&LogynoAtelier.txt
作者: 522235677    时间: 2014-5-3 18:23

回复 3# ZeronoFreya
  1. @echo off
  2. for /f "delims=" %%a in ('dir /b "%~1"') do (
  3.   for /f "tokens=1,2,3,4,5,6,7,8 delims=[]" %%b in ("%%~nxa") do ren "%~1\%%a" "%%b%%c%%d%%e%%f%%g%%h%%i%%~xa"
  4. )
  5. pause
复制代码
你上面说的也只有一个中括号啊,所以你得说清楚
作者: CrLf    时间: 2014-5-3 19:28

回复 3# ZeronoFreya


    那你要保留哪一部分呢?只留数字?
作者: g495326    时间: 2014-5-3 20:39

本帖最后由 g495326 于 2014-5-3 20:48 编辑
  1. @echo off
  2. setlocal enabledelayedexpansion
  3. if "%~1" == "" (
  4. set /p path=请输入需要修改的文件夹
  5. if "!path:~2,1!" equ ":" (
  6. set path=!path:~1,-1!
  7. )
  8. ) else (
  9. set path=%~1
  10. )
  11. set /p name=请输入需要修改的文件名,可以包含通配符:
  12. set /p order=请输入排序方式^(n:名称;e:扩展名;d:时间;s:大小;-:否定^):
  13. set /p main=设置需要修改成的文件名的公共部分:
  14. set /p num=请输入开始序列(直接回车默认为1)
  15. if not defined num (
  16. set num=1
  17. )
  18. echo.
  19. for /f "delims=" %%i in ('dir /a-d /b /o%order% "%path%\%name%"') do (
  20. if "%%i" neq "%~nx0" (
  21. echo 正在处理: "%path%\%%i"
  22. ren "%path%\%%i" %main%!num!%%~xi
  23. set /a num+=1
  24. )
  25. )
  26. echo.
  27. echo All Done
  28. echo Press any key to exit
  29. pause>nul
复制代码

作者: ZeronoFreya    时间: 2014-5-3 20:54

本帖最后由 ZeronoFreya 于 2014-5-4 11:43 编辑

回复 5# CrLf


    嗯,只留数字,数值范围在00-99,
作者: terse    时间: 2014-5-3 21:02

有没有种情况 那么怎么处理的
[02][Escha&LogynoAtelier~][01][CB].txt
作者: apang    时间: 2014-5-3 23:12

本帖最后由 apang 于 2014-5-3 23:14 编辑
  1. @set @n=0;/* & echo off
  2. if "%~1" == "" echo,请拖拽文件夹&pause&exit
  3. if not exist "%~1\" echo,请拖拽文件夹&pause&exit
  4. pushd "%~1\"
  5. for /f "delims=" %%a in ('dir/b/s *.txt^|cscript -nologo -e:jscript %0')do (
  6.     echo,Ren %%a 2>nul
  7. )
  8. pause & exit/b & rem */
  9. while (!WScript.StdIn.AtEndOfStream) {
  10.     f = WScript.StdIn.ReadLine();
  11.     name = f.replace(/.*?\[(\d{2})][^\\]*$/, "$1");
  12.     if (f != name) {
  13.         WScript.StdOut.WriteLine('"' + f + '" "' + name + '.txt"');
  14.     };
  15. }
复制代码

作者: CrLf    时间: 2014-5-4 02:19

本帖最后由 CrLf 于 2014-5-4 02:31 编辑

有 sed 可以这样:
  1. @dir /s /a-d /b *.txt | sed "s/.*\[\([0-9][0-9]\)\][^\\]*/ren \"^&\" \"\1.txt\"/;ta;d;:a" | cmd
复制代码

作者: CrLf    时间: 2014-5-4 02:19

本帖最后由 CrLf 于 2014-5-4 02:31 编辑

有 gawk 可以这样:
  1. @dir /s /a-d /b *.txt | gawk -F "\\" "{q=\"\x22\";if(match($NF,\"\\[[0-9]{2}\\]\",a))system(\"cmd /c ren\",q $NF q,q substr(a[0],2,2) \".txt\" q)}"
复制代码

作者: CrLf    时间: 2014-5-4 02:19

本帖最后由 CrLf 于 2014-5-4 03:22 编辑

本来想贴个 powershell 方案的,但试了下这么简单的事竟然在 xp 和 win7 下都报错,什么原因?
  1. (Get-ChildItem -Recurse *.txt) -Match "\[\d\d\]" | Rename-Item -NewName {$_.name -replace '.*\[(\d\d)\].*','$1.txt'}
复制代码
测试中对 te[01]st.txt 报错如下,而改成匹配 te(01)st.txt 却能正确执行:
Rename-Item : 无法重命名,因为“te[01]st.txt”处不存在项。
......

再测试下最简单的 ReName-Item 'test.txt' 'test[0].txt' 同样会报错,这是 bug 还是另有什么隐晦的规矩?
百度不到,搞不明白咋回事,哪位知道的能否指点个?拜谢~
作者: terse    时间: 2014-5-4 02:43

加参数 I 有用不
作者: CrLf    时间: 2014-5-4 02:46

修改自 9 楼 apang 胸的代码:
  1. @set @n=0;/* & echo off
  2. if "%~1" == "" echo,请拖拽文件夹&pause&exit
  3. if not exist "%~1\" echo,请拖拽文件夹&pause&exit
  4. pushd "%~1\"
  5. for /f "delims=" %%a in ('dir/b/s *.txt^|findstr "\[[0-9][0-9]\][^\\]*$"^|cscript -nologo -e:jscript %0')do (
  6.     Ren %%a 2>nul
  7. )
  8. pause & exit/b */
  9. var text = WScript.StdIn.ReadAll().replace(/\r|\n$/g,'')
  10. WScript.Echo(text.replace(/^(.*?[^\\]*\[(\d{2})\][^\\]*)$/gm, '"$1" "$2.txt"'))
复制代码
代码会短一些,但可读性其实很差
作者: terse    时间: 2014-5-4 03:25

本帖最后由 terse 于 2014-5-4 11:53 编辑

没考虑子目录 修正
ps不考虑效率
  1. (Get-ChildItem  * -Recurse -include "*.txt") -Match "\[\d\d\]" | % {$_.MoveTo($_.DirectoryName + ($_.name -Replace '.*\[(\d{2})\].*','\$1.txt'))}
复制代码
加个参数 literalpath
  1. (Get-ChildItem  * -Recurse -include "*.txt") -Match "\[\d\d\]" | foreach { move-item -LiteralPath  $_ ($_.DirectoryName + ($_.Name -Replace '.*\[(\d\d)\].*','\$1.txt'))}
复制代码

作者: ZeronoFreya    时间: 2014-5-4 11:34

回复 8# terse


    不会的,确定只有一组 两位 数字...
作者: apang    时间: 2014-5-5 22:35

遗憾的是都一闪而过,没能达成要求...,顺带一提,系统是win7 64位 旗舰版...


遗憾的是你一点都不会,找找自身的原因吧,要么复制粘贴有问题,要么保存bat时编码有问题

本想改改顶楼vbs代码,估计给你也白搭,算了吧
作者: CrLf    时间: 2014-5-6 00:11

同上,估计是楼主保存成 unicode 了吧?这么多代码不至于一个都不能用
作者: terse    时间: 2014-5-7 02:14

回复 1# ZeronoFreya
这样试下呢?
无64位环境测试  请自行备份数据
  1. @if(0)==(0) echo off
  2. set "Sysdir=SysWOW64"
  3. if /i "%PROCESSOR_ARCHITECTURE%" == "x86" if not defined PROCESSOR_ARCHITEW6432 set "Sysdir=System32"
  4. set cscript="%Windir%\%Sysdir%\cscript.exe" //nologo //e:javascript
  5. if "%~1" == "" (set "ph=%~dp0") else set "ph=%~1\"
  6. for /f "delims=" %%i in ('dir/b/s "%ph%*[*]*.txt"^|%cscript% "%~f0"')do (
  7.     echo,Ren %%i 2>nul
  8. )
  9. pause
  10. goto :eof
  11. @end
  12. while (!WScript.StdIn.AtEndOfStream) {
  13.     var f = WScript.StdIn.ReadLine()
  14.     var arr = f.match(/(\[(\d{2})\])/)
  15.     if (arr) WScript.echo('"' + f + '"','"' + arr[2] + '.txt"');
  16. }
复制代码

作者: ZeronoFreya    时间: 2014-5-7 15:40

回复 19# terse


    Ren "D:\system\Desktop\test\test\dgtsts[02]fhjfcct.mp4.mp4" "02.mp4"
Ren "D:\system\Desktop\test\test\sdgdd[01]fdtgs.mp4" "01.mp4"
请按任意键继续. . .


感谢,但还是不成功。

我不懂编程,但感觉我的要求应该不是很难...没想到有这么多人帮助还是不行,这时候放弃也是不错的选择,再一次,感谢大家的帮助!!
作者: CrLf    时间: 2014-5-7 16:16

回复 20# ZeronoFreya


    大哥,你得把 Ren 前的那个 echo 去掉,他那是为了显示出来让你看看是否正确,确认无误后去掉 echo 再进行实际的改名操作
作者: terse    时间: 2014-5-7 18:39

回复 20# ZeronoFreya
上面显示表明代码可正常运行
如要统配后缀可以改下这样试
虽然楼主放弃了 还是贴出吧
  1. @if(0)==(0) echo off
  2. set "Sysdir=SysWOW64"
  3. if /i "%PROCESSOR_ARCHITECTURE%" == "x86" if not defined PROCESSOR_ARCHITEW6432 set "Sysdir=System32"
  4. set cscript="%Windir%\%Sysdir%\cscript.exe" //nologo //e:javascript
  5. if "%~1" == "" (set "ph=%~dp0") else set "ph=%~1\"
  6. for /f "delims=" %%i in ('dir/b/s "%ph%*[*]*.*"^|%cscript% "%~f0"')do Ren %%i 2>nul
  7. pause
  8. goto :eof
  9. @end
  10. while (!WScript.StdIn.AtEndOfStream) {
  11.     var f = WScript.StdIn.ReadLine()
  12.     var e =/\.[^\.]+$/.exec(f);
  13.     var arr = f.match(/(\[(\d{2})\])/)
  14.     if (arr) WScript.echo('"' + f + '"','"' + arr[2] + e + '"');
  15. }
复制代码

作者: PakTC    时间: 2014-5-7 19:31

修改自 9 楼 apang 胸的代码:代码会短一些,但可读性其实很差
CrLf 发表于 2014-5-4 02:46



    “apang胸”
作者: PakTC    时间: 2014-5-7 19:51

本帖最后由 PakTC 于 2014-5-7 20:06 编辑


重命名这种事情要是没有特殊控制字符干嘛要用vbs?

回复 14# CrLf
  1. @echo off
  2. setlocal enabledelayedexpansion
  3. for /l %%a in (1,1,99) do (
  4.     set sn=0%%a
  5.     set sn=!sn:~-2!
  6.     if exist *[!sn!]*.txt (
  7.         call :next *[!sn!]*.txt !sn!
  8.     )
  9. )
  10. echo 修改之后的文件列表:
  11. dir /b *.txt
  12. pause
  13. exit
  14. :next
  15. echo "%~f1"
  16. ren "%~f1" !sn!.txt
复制代码
输出结果
"C:\新建文件夹\###[01]#####.txt"
"C:\新建文件夹\复件 ###[02]#####.txt"
"C:\新建文件夹\复件 (3) ###[03]#####.txt"
"C:\新建文件夹\复件 (2) ###[04]#####.txt"
修改之后的文件列表:
01.txt
02.txt
03.txt
04.txt

作者: CrLf    时间: 2014-5-7 20:32

回复 24# PakTC


    楼主要求有这一项:
(包含子文件夹)

作者: PakTC    时间: 2014-5-8 09:45

回复 25# CrLf


不要做拖放了,用vbs循环访问剪切板中的信息。当出现目录的时候,对该目录进行重命名操作。
这样就只要在指定目录按ctrl+c就可以执行操作了。
作者: 523066680    时间: 2014-5-8 12:48

本帖最后由 523066680 于 2014-5-8 12:51 编辑

回复 1# ZeronoFreya

按楼主的代码添加了一部分东西,保存为vbs即可,WIN7 64位,测试过

if wscript.arguments.count=0 then
   createobject("wscript.shell").run _
   "cmd /c cscript //nologo " &chr(34) &wscript.scriptname &chr(34) & " isme"
   wscript.quit
end if

set OUT=wscript.stdout
set INP=wscript.stdin
OUT.write "拖放需要改名的文件夹到此处:"
fold=INP.readline

'以下是楼主的代码
Set FSO = CreateObject("Scripting.FileSystemObject")
For Each File in FSO.GetFolder(fold).Files
   Ext = FSO.GetExtensionName(File)
   If LCase(Ext) = "txt" Or LCase(Ext) = "doc" Or LCase(Ext) = "ass" Then RenFiles
Next
MsgBox "OK"

Sub RenFiles()
   Set Re = New RegExp
   Re.Pattern = "(^.*\[)(\d{2})(\].*$)"
   Re.Global = True
   File.Name = Re.Replace(File.Name,"$2") & "." & Ext
End Sub

作者: ZeronoFreya    时间: 2014-5-8 16:25

回复 24# PakTC


    没想到放弃后会出现满意结果,不能处理子文件夹也可以了,嗯,非常满意了,非常感谢!!
作者: ZeronoFreya    时间: 2014-5-8 16:30

回复 21# CrLf


    惭愧,如楼上所说,我不懂批处理,看到文件夹内内容未变,就果断认为失败了...惭愧!!
作者: ZeronoFreya    时间: 2014-5-8 16:34

回复 27# 523066680


    感谢,我决定用PakTC的批处理了,放到文件夹根目录下效果很不错,再次感谢




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