Board logo

标题: [文件操作] 求批量修改文件名(增加前缀)的批处理代码或c代码 [打印本页]

作者: yylogo    时间: 2008-10-7 18:02     标题: 求批量修改文件名(增加前缀)的批处理代码或c代码

家有电脑一台,两年来下载歌曲近六千首,歌曲分门别类,装在不同文件夹下。如:中国,外国。。。中国文件夹之下再分男、女、组合。。。等文件夹。男之下再分周杰伦、任贤齐。。。等文件夹,周杰伦之下就是歌曲文件,歌曲名我以前都慢慢的整理过,一般去掉了专辑名,去掉了01、02等号码,只剩下了纯歌名。有学生来下载歌曲,很容易查找。后用浏览器的“搜索”找歌曲也很快,但歌曲多了以后,出现了一个问题,那就是同一首歌名,有不同的歌手唱过,如果要复制到mp3,mp4或手机内存卡去的话,就会出现同名歌曲的覆盖,必须修改歌名才能分别复制。例如:费玉清的“千里之外.mp3”和周杰伦的“千里之外.mp3”不能同时复制到另一个文件夹中,因为文件名相同。所以我想修改所有歌曲的名字,在原歌曲名之前加一个前缀,即添加歌曲最近的那个文件夹的名字再加一个下划线。如:费玉清的“千里之外.mp3”,改为“费玉清_千里之外.mp3”,文件夹不改名。
六千首歌曲一个一个该非常麻烦,也容易出错,希望能有一个批处理文件一次解决,一可以省时省力,二可以突显批处理的魅力,三还可以学习到编程的知识。
ps:歌曲有两种格式  .mp3和.wma
第一次发帖不知符不符合规矩,我会慢慢向大家学习的。谢谢各位看客。
作者: 随风    时间: 2008-10-7 18:22

  1. @echo off
  2. for /f "delims=" %%a in ('dir/b/s/a-d *.mp3 *.wma') do (
  3.    for /f "delims=" %%i in ("%%~dpa.") do ren "%%a" "%%~ni_%%~nxa"
  4. )
  5. pause
复制代码

[ 本帖最后由 随风 于 2008-10-7 18:33 编辑 ]
作者: pusofalse    时间: 2008-10-7 18:30

  1. @echo off&setlocal enabledelayedexpansion
  2. for /r %%a in (*.wma *.mp3) do (
  3.          if not defined %%~dpa set "var=%%~dpa"&set "%%~dpa=a"
  4.          for %%i in ("!var:~,-1!") do echo ren "%%a" "%%~ni_%%~nxa"
  5. )
  6. pause
复制代码
请及时反馈测试信息,如果发现输出正确(原文件名与改后的文件名正确对应),则把
第4行的echo去掉。

[ 本帖最后由 pusofalse 于 2008-10-7 23:11 编辑 ]
作者: yylogo    时间: 2008-10-7 20:24     标题: 我的反馈信息

谢谢楼上两位的回答。
经过测试,我发现2楼的基本达到要求。
3楼的程序在运行的界面上是成功的,但最后的实际情况是没有任何文件名发生改变,不知何故。
我其实不只是想要效果,更希望得到“知其然,亦知其所以然”。回答者是否可以略加一点说明。比如:.bat文件的放置地点,以及由于错误的放置导致其他文件的名字的改变如何还原等等。
总之,谢谢,我觉得贵网站一级棒。专业负责,好,非常好。
作者: pusofalse    时间: 2008-10-7 20:30

你知道看到了及时反馈信息,没有看到后面的话。。。请及时反馈测试信息,如果发现输出正确(原文件名与改后的文件名正确对应),则把第4行的echo去掉。

[ 本帖最后由 pusofalse 于 2008-10-7 23:11 编辑 ]
作者: namejm    时间: 2008-10-7 23:42

  以上两个代码都必须放在歌手名文件夹所在的文件夹下使用,只有这样使用,才能保证获取到且只获取到你想要的音乐文件的完整路径名,并且,为后面的for语句正确地解析这些路径字符串提供保证。

  随风的思路是:用 dir /a-d /b /s 来获取完整路径名,放到for语句中来解析完整路径字符串,用 %%~dpa. 来获取音乐文件所处的文件夹完整路径(这里使用了一个小技巧:在字符串最后添加一个点号,从而使得for语句的%%~ni把文件夹名当做文件名来处理),再用 %%~ni 获取文件夹名,也就是歌手名,把这个歌手名用下划线连接到原来的文件名前面,用ren来实现改名——%%~nxi 获取原文件完整的文件名和后缀名。

  pusofalse的思路与随风大致相同,只不过在获取音乐完整路径的时候,换用了效率更高的 for /r 语句,并用一个变量var来获取音乐文件所在文件夹的完整路径,通过判断var是否经过赋值来判断当前处理的音乐文件是否位于同一目录下,因为直接用 %%~dpa 获取到的字符串最后有一个反斜杠,所以,第二个for语句中,用 !var:~,-1! 把最后的反斜杠去掉了(在for语句内部,如果要引用已经发生了改变的变量,必须使用变量延迟功能,也就是最开始的 setlocal 语句),后面的思路和随风的一样。其实,pusofalse的代码大可不必判断当前处理的文件与上一次处理的文件是否位于同一目录下,因为 for /r 的时候,会获得文件的完整路径,只需要对完整路径直接进行操作就可以了,可以借鉴随风的做法,在 %%~dpa 的时候,直接在最后加上一个点号,可以使得效率进一步提升。

  说实话,解释代码是比较累人的,很多人宁肯写上百行代码,也不想解释其中的意思,因为往往是解释内容比代码内容还多,并且也不见得别人能领会你的意思,要想看懂别人的代码,还是需要有一点基础了才好办,楼主不仅仅想知其然,还想知其所以然,这样的想法是非常值得提倡的,不过,还是需要先潜水一段时间,多翻翻论坛老帖,特别是教学区的帖子,才会有所收获。
作者: pusofalse    时间: 2008-10-8 00:03     标题: 回复 6楼 的帖子

多谢JM指点,修改如下:
  1. @echo off
  2. for /r /d %%a in (*) do (
  3.       for %%i in ("%%a\*.wma" "%%a\*.mp3") do ren "%%i" "%%~na_%%~nxi"
  4. )
  5. pause
复制代码

作者: yylogo    时间: 2008-10-8 02:52     标题: 谢谢楼上各位朋友

谢谢楼上各位朋友,当然不包括自己。
我刚才从贵站另一个帖子忙乎过来,发现这张帖子又有仙人指路了。
其实一个谢字无法表达我现在的真情实感。
尘土飞扬要我先潜水学习,可你们的热情让我没法潜下心来。
我上面的问题已经被你们解决了,然后发现标准的答案已不是很重要了,重要的是希望在此学到代码以外的东西。
作者: namejm    时间: 2008-10-9 20:33

  在 for /f 语句中,第一个括号里的内容该如何引用,有如下规则:
  1) 若读取的是某个文件的内容,只需要填写该文件的绝对路径或相对路径即可;如 for /f %%i in (test.txt) do ……
  2) 若读取的是某个字符串,则该字符串应该用双引号把该字符串括起来,如 for /f %%i in ("bbs.bathome.net") do ……
  3) 若读取的是某条命令或者某条复合语句返回的结果,则需要用单引号把这条命令或者这条复合语句括起来,比如 for /f %%i in ('dir /a-d /b /s') do ……,又比如 for /f %%i in ('dir /a-d /b /s^|findstr /i "txt"') do ……

  第一个括号内更复杂的引用规则,在此不再深入探讨。
作者: yylogo    时间: 2008-10-10 17:29

我也出现过这样的问题
作者: namejm    时间: 2008-10-10 18:13

  解决由于多次重命名造成歌手名累加的问题,可以使用如下代码:
  1. @echo off
  2. setlocal enabledelayedexpansion
  3. for /f "delims=" %%i in ('dir/b/s/a-d *.mp3 *.wma') do (
  4.     set "str=%%~nxi"
  5.     for /f "delims=" %%j in ("%%~dpi.") do (
  6.         set str=!str:%%~nj_=!
  7.         ren "%%i" "%%~nj_!str!"
  8.     )
  9. )
  10. pause
复制代码

作者: wxcute    时间: 2008-10-10 18:19

关于歌手名(即目录名)累加问题,我也写了个
我喜欢标签子程序写在外面,已测试
  1. @echo off
  2. for /f "delims=" %%a in ('dir/b/s/a-d *.mp3 *.wma') do (
  3.  for /f "delims=" %%i in ("%%~dpa.") do call :new fn dn "%%a" "%%i"
  4. )
  5. goto :eof
  6. :new
  7.  set %1=%~nx3
  8.  set %2=%~n4
  9. :newName
  10.  if not "%fn:*_=%"=="%fn%" set fn=%fn:*_=%&goto :newName
  11.  ren %3 "%dn%_%fn%"
  12.  goto :eof
复制代码

作者: namejm    时间: 2008-10-10 18:42

原帖由 ezfriend 于 2008-10-10 18:18 发表
我试了的,没有用呀!还在在重复累加!

  经过实际测试,我在14楼的代码完全可以实现在文件名前添加歌手信息,如果歌手信息有重复,完全可以清除。若还在累加,则说明你的路径格式和楼主的不一样,或者不是用前面所提供的代码生成文件名。
作者: namejm    时间: 2008-10-11 11:55

  set str=!str:%%~nj_=! 的意思是删除文件名中所有的 文件夹名_ 这个字符串,也就是删除音乐文件名中的歌手信息,其中,%%~nj 表示文件夹名。
作者: Batcher    时间: 2008-10-11 13:41     标题: 回复 18楼 的帖子

for /?
另外,FOR 变量参照的替换已被增强。您现在可以使用下列
选项语法:

     ~I         - 删除任何引号("),扩充 %I
     %~fI        - 将 %I 扩充到一个完全合格的路径名
     %~dI        - 仅将 %I 扩充到一个驱动器号
     %~pI        - 仅将 %I 扩充到一个路径
     %~nI        - 仅将 %I 扩充到一个文件名
     %~xI        - 仅将 %I 扩充到一个文件扩展名
     %~sI        - 扩充的路径只含有短名
     %~aI        - 将 %I 扩充到文件的文件属性
     %~tI        - 将 %I 扩充到文件的日期/时间
     %~zI        - 将 %I 扩充到文件的大小
     %~$PATH:I   - 查找列在路径环境变量的目录,并将 %I 扩充
                   到找到的第一个完全合格的名称。如果环境变量名
                   未被定义,或者没有找到文件,此组合键会扩充到
                   空字符串

可以组合修饰符来得到多重结果:

     %~dpI       - 仅将 %I 扩充到一个驱动器号和路径
     %~nxI       - 仅将 %I 扩充到一个文件名和扩展名
     %~fsI       - 仅将 %I 扩充到一个带有短名的完整路径名
     %~dp$PATH:i - 查找列在路径环境变量的目录,并将 %I 扩充
                   到找到的第一个驱动器号和路径。
     %~ftzaI     - 将 %I 扩充到类似输出线路的 DIR

在以上例子中,%I 和 PATH 可用其他有效数值代替。%~ 语法
用一个有效的 FOR 变量名终止。选取类似 %I 的大写变量名
比较易读,而且避免与不分大小写的组合键混淆。





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