[新手上路]批处理新手入门导读[视频教程]批处理基础视频教程[视频教程]VBS基础视频教程[批处理精品]批处理版照片整理器
[批处理精品]纯批处理备份&还原驱动[批处理精品]CMD命令50条不能说的秘密[在线下载]第三方命令行工具[在线帮助]VBScript / JScript 在线参考
返回列表 发帖

[文本处理] [已解决]批处理在启动变量延迟的情况下怎么处理惊叹号?

  假设一个“recent.m3u”文件(播放列表文件),里面的内容如下:
  1. D:\a\ahaha\abc!.mp3
  2. D:\a\ohoho\a&bc.mp3
复制代码
  (列表中只列出两个特殊的例子,本人真正在弄的是有上千个文件的列表。)
  我想把列表中的文件,从“D:\a”复制到“D:\b”,且保留“D:\a”之下的目录结构。
  也就是复制成“D:\b\ahaha\abc!.mp3”和“D:\b\ohoho\a&bc.mp3”。
  然后由于“ahaha”和“ohoho”文件夹下有一些文件我不想要复制,所以不能用选中“ahaha”和“ohoho”然后复制粘贴的方法……
  这样一来就得用批处理了……第一次,我的代码是这样的:
  1. echo off & cls
  2. setlocal enabledelayedexpansion
  3. rem ==============================
  4. rem 变量定义
  5. set "rsc=D:\a"
  6. set "rplc=D:\b"
  7. rem ==============================
  8. rem 复制m3u播放列表中的文件,并在一定程度上保留其目录结构
  9. for /f "usebackq tokens=* eol=; delims=" %%a in ("recent.m3u") do (
  10. set "spth=%%a"
  11. set "pth=%%a"
  12. set "pth=!pth:%rsc%=%rplc%!"
  13. echo.!spth!
  14. call :MakeFolder "!pth!"
  15. if not exist "!pth!". (
  16.   if not exist "!pth!". (
  17.   copy /y "!spth!" "!pth!"
  18. ) else (
  19.   echo.已存在,跳过!
  20. )
  21. )
  22. endlocal
  23. exit/b
  24. rem ==============================
  25. rem 创建目录的、类似于“函数”的存在
  26. :MakeFolder
  27. set "pth1=%~dp1"
  28. if not exist "%pth1%". md "%pth1%"
复制代码
  用了上面的代码后发现只要m3u列表中的文件名中含有!、&等特殊符号的时候,这个文件就会复制失败,而其他文件OK!
  经过疯狂的尝试,我用一个本人非常不喜欢的做法解决了它。于是代码变成这样……同时问题也解决了……
  1. echo off & cls
  2. rem ==============================
  3. rem 变量定义
  4. set "rsc=D:\a"
  5. set "rplc=D:\b"
  6. rem ==============================
  7. rem 复制m3u播放列表中的文件,并在一定程度上保留其目录结构
  8. for /f "usebackq tokens=* eol=; delims=" %%a in ("recent.m3u") do (
  9. set "spth=%%a"
  10. set "pth=%%a"
  11. SETLOCAL ENABLEDELAYEDEXPANSION
  12. set "pth=!pth:%rsc%=%rplc%!"
  13. echo.!spth!
  14. call :MakeFolder "!pth!"
  15. if not exist "!pth!". (
  16.   copy /y "!spth!" "!pth!"
  17. ) else (
  18.   echo.已存在,跳过!
  19. )
  20. ENDLOCAL
  21. )
  22. pause
  23. exit/b
  24. rem 创建目录的、类似于“函数”的存在
  25. :MakeFolder
  26. set "pth1=%~dp1"
  27. if not exist "%pth1%". md "%pth1%"
  28. GOTO :EOF
复制代码
  问题解决,经过反向推测,问题应该出在for语句一开始给“spth”和“pth”赋值为“%%a”这里。在第一个代码里,这个时候的变量延缓是开着的。所以,MP3文件名中的“!”就被当成是变量的标识符了,所以文件名赋到变量里的时候就已经出错了。
  而在第二个代码里,把变量延迟放到赋值后才打开,这样赋到变量里的文件名就没错了……
  不过在FOR语句里面不停地SETLOCAL、ENDLOCAL感觉不太爽,哪位大哥有更好的解决办法?

  还有那位说把!换成^!的兄台,首先要声明,文件名是从列表中读取的,所以不可能预先把!改成^!,就算要用set来替换也很麻烦。
  然后请你试一下,在开启变量延迟的情况下,定义一下变量
  1. set "a=1"
复制代码
,然后用
  1. echo.^!a^!
复制代码
,就像下面的代码,如果你的想法正确的话,结果会是这样:“!a!=我的变量”,但结果不是……
  1. echo off & cls
  2. setlocal enabledelayedexpansion
  3. set "a=我是变量"
  4. echo.^!a^!=!a!
  5. endlocal
  6. pause
  7. exit/b
复制代码

[ 本帖最后由 MantisLin 于 2011-2-24 23:17 编辑 ]
1

评分人数

    • Batcher: 感谢给帖子标题标注[已解决]字样PB + 2

方法一:
关闭变量延迟,改用call echo %%变量%%
方法二:
如果非要用变量延迟的话,可以利用预处理,比如:
  1. set 感叹号=!
  2. setlocal enabledelayedexpansion
  3. echo !感叹号!
  4. pause
复制代码

[ 本帖最后由 zm900612 于 2011-2-22 17:54 编辑 ]

TOP

回复 2楼 的帖子

好吧,代码是这样的:
  代码的作用在注释中已经有说明,问题就出在当播放列表中,MP3文件名中包含有惊叹号“!”或者“&”等特殊符号的时候,复制会失败。
  这个地方貌似也不能用预处理。能否帮我解决一下?
  1. echo off & cls
  2. setlocal enabledelayedexpansion
  3. rem 作用:复制m3u播放列表中的文件并保留一定的目录结构
  4. rem 说明 所有文件都在"%rsc%"文件夹中,将这些文件复制到"%rplc%"文件夹下
  5. rem    保留剩下的子文件夹的目录结构
  6. rem ==============================
  7. rem 变量定义
  8. set "rsc=D:\Melody"
  9. set "rplc=%~dp0recent"
  10. set "succ=0"
  11. set "faic=0"
  12. set "pasc=0"
  13. rem ==============================
  14. rem 复制m3u播放列表中的文件,并在一定程度上保留其目录结构
  15. for /f "usebackq tokens=* eol=; delims=" %%a in ("recent.m3u") do (
  16.         set "spth=%%a"
  17.         set "pth=%%a"
  18.         set "pth=!pth:%rsc%=%rplc%!"
  19.         echo.!spth!
  20.         call :MakeFolder "!pth!"
  21.         if not exist "!pth!". (
  22.                 copy /y "!spth!" "!pth!" && (
  23.                         set /a "succ=succ+1"
  24.                 ) || (
  25.                         set /a "faic=faic+1"
  26.                 )
  27.         ) else (
  28.                 echo.已存在,跳过!
  29.                 set /a "pasc=pasc+1"
  30.         )
  31. )
  32. rem Log数据打印
  33. echo.
  34. echo. 成功数:%succ%
  35. echo. 失败数:%faic%
  36. echo. 跳过数:%pasc%
  37. setlocal disabledelayedexpansion
  38. echo.
  39. echo.  按任意键退出……
  40. pause>nul
  41. exit/b
  42. rem 创建目录的、类似于“函数”的存在
  43. :MakeFolder
  44. set "pth1=%~dp1"
  45. if not exist "%pth1%". md "%pth1%"
复制代码

TOP

大概改了一下,没测试,这样可以避免使用变量扩展:
  1. @echo off & cls
  2. rem 作用:复制m3u播放列表中的文件并保留一定的目录结构
  3. rem 说明 所有文件都在"%rsc%"文件夹中,将这些文件复制到"%rplc%"文件夹下
  4. rem    保留剩下的子文件夹的目录结构
  5. rem ==============================
  6. rem 变量定义
  7. set "rsc=D:\Melody"
  8. set "rplc=%~dp0recent"
  9. set "succ=0"
  10. set "faic=0"
  11. set "pasc=0"
  12. rem ==============================
  13. rem 复制m3u播放列表中的文件,并在一定程度上保留其目录结构
  14. for /f "usebackq tokens=* eol=; delims=" %%a in ("recent.m3u") do call set %%a
  15. rem Log数据打印
  16. echo.
  17. echo. 成功数:%succ%
  18. echo. 失败数:%faic%
  19. echo. 跳过数:%pasc%
  20. echo.
  21. echo.  按任意键退出……
  22. pause>nul
  23. exit/b
  24. rem 创建目录的、类似于“函数”的存在
  25. :set
  26. set "spth=%%a"
  27. set "pth=%*"
  28. for %%a in ("%rsc%" "%rplc%") do set "pth=%pth:%%~a=%%~b%"
  29. echo.%spth%
  30. set "pth1=%pth%"
  31. if not exist "%pth1%". md "%pth1%"
  32. if not exist "%pth%". (
  33. copy /y "%spth%" "%pth%" && (
  34.         set /a "succ=succ+1"
  35.         ) || (
  36.         set /a "faic=faic+1"
  37.         )
  38.         ) else (
  39.         echo.已存在,跳过!
  40.         set /a "pasc=pasc+1"
  41.         )
复制代码

[ 本帖最后由 zm900612 于 2011-2-22 20:04 编辑 ]

TOP

回复 4楼 的帖子

不行啊,我运行了一下,结果是这样的……
  1. 环境变量 D:\Melody\南拳妈妈\下雨天.mp3 没有定义
  2. 环境变量 D:\Melody\容祖儿\爱情复兴.mp3 没有定义
  3. 环境变量 D:\Melody\容祖儿\挥着翅膀的女孩.mp3 没有定义
  4. 环境变量 D:\Melody\水木年华\一生有你.mp3 没有定义
  5. 环境变量 D:\Melody\水木年华\在他乡.mp3 没有定义
  6. 环境变量 D:\Melody\孙悦\哭泣的百合花.mp3 没有定义
  7. 环境变量 D:\Melody\汤灿\家乡美.mp3 没有定义
  8. 环境变量 D:\Melody\汤灿\幸福万年长.mp3 没有定义
  9. 环境变量 D:\Melody\王力宏\大城小爱.mp3 没有定义
  10. 环境变量 D:\Melody\王力宏\龙的传人.mp3 没有定义
  11. 环境变量 D:\Melody\王强\秋天不回来.mp3 没有定义
  12. 环境变量 D:\Melody\王心凌\花的嫁纱.mp3 没有定义
  13. 环境变量 D:\Melody\王心凌\黄昏晓.mp3 没有定义
  14. 环境变量 D:\Melody\王心凌\我会好好的.mp3 没有定义
  15. 环境变量 D:\Melody\仙剑奇侠传\挥剑问情.mp3 没有定义
  16. 环境变量 D:\Melody\仙剑奇侠传\迴梦游仙·二胡独奏版.mp3 没有定义
  17. 环境变量 D:\Melody\仙剑奇侠传\仙剑问情.mp3 没有定义
  18. 环境变量 D:\Melody\仙剑奇侠传\御剑江湖.mp3 没有定义
  19. 环境变量 D:\Melody\仙剑奇侠传\织梦行云.mp3 没有定义
  20. 环境变量 D:\Melody\谢雨欣\天仙子.mp3 没有定义
  21. 环境变量 D:\Melody\徐怀钰\分飞.mp3 没有定义
  22. 环境变量 D:\Melody\许慧欣\七月七日晴.mp3 没有定义
  23. 环境变量 D:\Melody\许慧欣\特别来宾.mp3 没有定义
  24. 环境变量 D:\Melody\许慧欣\我要轻轻为你唱首歌.mp3 没有定义
  25. 环境变量 D:\Melody\銀魂\days.mp3 没有定义
复制代码

TOP

用^!来处理,表示为!字符,而不会解释成 变量符号。
其实我也是在处理 set /a 的NOT 符号 !时,发现在变量延迟环境下的运行结果天差地别。
试验了很多次,才发现需要带上^。

TOP

建议楼主在顶楼用文字把你的目的描述清楚,代码不但会给别人误导还会让人看得眼晕
技术问题请到论坛发帖求助!

TOP

回复 1楼 的帖子

个人认为最好的办法是:将变量放在延迟语句的前面。拿你1L为例(3L的太长了,没心去看)
  1. @echo off
  2. set "pth=abcabc!.mp3"
  3. setlocal enabledelayedexpansion
  4. echo.!pth!
  5. setlocal disabledelayedexpansion
  6. pause
  7. exit/b
复制代码
即可
枫中残雪:风停了,我的心却在动,让我心中的寒意走向远方

TOP

回复 8楼 的帖子

echo,比echo.效率稍高
我帮忙写的代码不需要付钱。如果一定要给,请在微信群或QQ群发给大家吧。
【微信公众号、微信群、QQ群】http://bbs.bathome.net/thread-3473-1-1.html
【支持批处理之家,加入VIP会员!】http://bbs.bathome.net/thread-67716-1-1.html

TOP

回复 9楼 的帖子

主要是时间上的么?但是echo/比ECHO输出更多的东西,
枫中残雪:风停了,我的心却在动,让我心中的寒意走向远方

TOP

8楼代码没考虑到setlocal最大递归层数,在循环中极易出错。但是直接endlocal又会丢失变量,所以循环中建议这样:
  1. @echo off
  2. set "pth=abcabc!.mp3"
  3. setlocal enabledelayedexpansion
  4. for /f "delims=" %%a in ("!pth!") do (
  5.    endlocal
  6.    echo %%a
  7. )
  8. pause
复制代码

[ 本帖最后由 zm900612 于 2011-2-27 23:21 编辑 ]
1

评分人数

TOP

回复 11楼 的帖子

确实没有想到,也可以说这方面用的太少了
枫中残雪:风停了,我的心却在动,让我心中的寒意走向远方

TOP

回复 10楼 的帖子

为什么会输出更多的东西?
我帮忙写的代码不需要付钱。如果一定要给,请在微信群或QQ群发给大家吧。
【微信公众号、微信群、QQ群】http://bbs.bathome.net/thread-3473-1-1.html
【支持批处理之家,加入VIP会员!】http://bbs.bathome.net/thread-67716-1-1.html

TOP

原帖由 Batcher 于 2011-2-23 12:48 发表
echo,比echo.效率稍高


这样的用法跟预处理是什么关系啊?还看见batman用call,这样的用法
__@__@__批了___来看看吧

TOP

回复 14楼 的帖子

我帮忙写的代码不需要付钱。如果一定要给,请在微信群或QQ群发给大家吧。
【微信公众号、微信群、QQ群】http://bbs.bathome.net/thread-3473-1-1.html
【支持批处理之家,加入VIP会员!】http://bbs.bathome.net/thread-67716-1-1.html

TOP

返回列表