Board logo

标题: [代码合集] [已解决]管道命令"|"在bat调用自身时有要求? [打印本页]

作者: zljzsmzzx    时间: 2009-7-2 12:55     标题: [已解决]管道命令"|"在bat调用自身时有要求?

下面这个代码用来获得一个拖到CMD窗口的文件的路径和后缀名。双击运行后第一次不会出错。当调用自身运行时就会出错。大家帮忙看看是不是代码本身出错了还是批处理调用自身有什么特别的“限制”?
  1. @echo off&color 0a&setlocal enabledelayedexpansion
  2. cls
  3. if "%~1"=="" (
  4.     if not defined hzm (
  5.         echo+请把要重命名的文件中任意一个文件拖到该窗口。
  6.         echo+注:本程序不支持没有后缀名的文件。
  7.         set "hzm="&set /p hzm=文件完整路径=
  8.         if "!hzm!" == "" (endlocal&%~s0&exit)
  9.         echo+!hzm!|findstr /i /v "[a-z]:">nul 2>nul&&(
  10.         endlocal&%~s0&exit
  11.         )||(
  12.             for /f "delims=" %%i in ("!hzm!") do (set "hzm=%%~xi"&set "hzm=!hzm:~1!"&set "path=%%~dpi")
  13.         )
  14.         %~s0&exit
  15.     )
  16.     echo+你要重命名的文件为:
  17.     echo+目录[%path%]下的所有[.%hzm%]文件。
  18. pause&set "hzm="&call %~s0&exit
  19. )
复制代码
[问题更新]好像已经找到问题之所在了。看5楼。请高手们解释解释。为什么批处理调用自身时只有传递新的环境给cmd.exe时管道命令"|"才有效呢?否则出错。[/问题更新]

[ 本帖最后由 zljzsmzzx 于 2009-7-3 17:06 编辑 ]
作者: keen    时间: 2009-7-2 21:44     标题: 回复 1楼 的帖子

换成if怎么个判断法?
可以给出代码吗?
作者: zljzsmzzx    时间: 2009-7-2 23:18

下面这个是我修改后的代码:
  1. @echo off&color 0a&setlocal enabledelayedexpansion
  2. cls
  3. if not defined hzm (
  4.     echo+请把要重命名的文件中任意一个文件拖到该窗口。
  5.     echo+注:本程序不支持没有后缀名的文件。
  6.     set "hzm="&set /p hzm=文件完整路径=
  7.     if "!hzm!" == "" (endlocal&%~s0&exit)
  8.     if "!hzm:~1,2!" neq ":\" if "!hzm:~2,2!" neq ":\" (endlocal&%~s0&exit)
  9.     call :hzm !hzm!
  10.     %~s0&exit
  11. )
  12. (
  13. echo+你要重命名的文件为:
  14. echo+目录[!path!]下的所有[.!hzm!]文件。
  15. pause&set "hzm="&%~s0&exit
  16. )
  17. :hzm
  18. set "path=%~dp1"
  19. set "hzm=%~x1"
  20. set "hzm=%hzm:~1%"
  21. goto eof
复制代码
原来的
echo+!hzm!|findstr /i /v "[a-z]:">nul 2>nul&&(
    endlocal&%~s0&exit
)||(
    for /f "delims=" %%i in ("!hzm!") do (set "hzm=%%~xi"&set "hzm=!hzm:~1!"&set "path=%%~dpi")
)
改为
if "!hzm:~1,2!" neq ":\" if "!hzm:~2,2!" neq ":\" (endlocal&%~s0&exit)

[ 本帖最后由 zljzsmzzx 于 2009-7-2 23:20 编辑 ]
作者: keen    时间: 2009-7-2 23:38     标题: 回复 3楼 的帖子

把你原先的代码不改成IF,只改CALL,也可以,原因未知:
  1. @echo off&color 0a&setlocal enabledelayedexpansion
  2. cls
  3. if "%~1"=="" (
  4.     if not defined hzm (
  5.         echo+请把要重命名的文件中任意一个文件拖到该窗口。
  6.         echo+注:本程序不支持没有后缀名的文件。
  7.         set "hzm="&set /p hzm=文件完整路径=
  8.         if "!hzm!" == "" (endlocal&%~s0&exit)
  9.         echo+!hzm!|findstr /i /v "[a-z]:">nul 2>nul&&(
  10.         endlocal&%~s0&exit
  11.         )||(
  12.             for /f "delims=" %%i in ("!hzm!") do (set "hzm=%%~xi"&set "hzm=!hzm:~1!"&set "path=%%~dpi")
  13.         )
  14.         %~s0&exit
  15.     )
  16.     echo+你要重命名的文件为:
  17.     echo+目录[%path%]下的所有[.%hzm%]文件。
  18. pause&set "hzm="&start /b /i %~s0&exit
  19. )
复制代码

作者: zljzsmzzx    时间: 2009-7-3 01:04

start /b /i %~s0在新的环境运行,相当于关闭之前的窗口重新双击运行。为什么会这样呢?刚才又测试了一下。好像是管道命令"|"在作怪。我把"|"去掉改成如下就不会出错了。
  1. @echo off&color 0a&setlocal enabledelayedexpansion
  2. cls
  3. if "%~1"=="" (
  4.     if not defined hzm (
  5.         echo+请把要重命名的文件中任意一个文件拖到该窗口。
  6.         echo+注:本程序不支持没有后缀名的文件。
  7.         set "hzm="&set /p hzm=文件完整路径=
  8.         if "!hzm!" == "" (endlocal&%~s0&exit)
  9.         echo+!hzm!>a.txt&findstr /i /v "[a-z]:" a.txt>nul 2>nul&&(
  10.         endlocal&%~s0&exit
  11.         )||(
  12.             for /f "delims=" %%i in ("!hzm!") do (set "hzm=%%~xi"&set "hzm=!hzm:~1!"&set "path=%%~dpi")
  13.         )
  14.         %~s0&exit
  15.     )
  16.     echo+你要重命名的文件为:
  17.     echo+目录[%path%]下的所有[.%hzm%]文件。
  18. pause&set "hzm="&call %~s0&exit
  19. )
复制代码
echo+!hzm!|findstr /i /v "[a-z]:">nul 2>nul
改成了
echo+!hzm!>a.txt&findstr /i /v "[a-z]:" a.txt>nul 2>nul

[ 本帖最后由 zljzsmzzx 于 2009-7-3 01:22 编辑 ]
作者: zqz0012005    时间: 2009-7-3 10:53

乱用系统环境变量作为普通变量名的后果!
path!你改了path的路径,再次运行时很多命令就找不到了。

至于你改成了echo+!hzm!>a.txt&findstr /i /v "[a-z]:" a.txt>nul 2>nul后为什么又正常,还有待研究。
  1. @echo off
  2. setlocal enabledelayedexpansion
  3. if 1==1 (
  4. set path=c:\
  5. rem 改变path后findstr立即无法运行。而楼主的代码中却可以,不知原因何在?
  6. findstr . c:\boot.ini
  7. findstr . c:\boot.ini && echo y || echo n
  8. pause 上面出错没有使整个bat退出,而下面在管道中出错导致整个bat退出,没有执行后面的命令。
  9. type c:\boot.ini|findstr .
  10. type c:\boot.ini|findstr . && echo y || echo n
  11. )
  12. pause
复制代码

作者: zljzsmzzx    时间: 2009-7-3 14:11     标题: 回复 6楼 的帖子

乱用系统环境变量作为普通变量名的后果!
path!你改了path的路径,再次运行时很多命令就找不到了。
一语惊醒梦中人啊。把变量名path改成其它的就可以了。但5楼的修改又为什么能找到findstr呢,没有传递新的环境给cmd.exe,变量path已经不是系统变量了啊。头晕了。
作者: zljzsmzzx    时间: 2009-7-3 17:05     标题: RE 6#

至于你改成了echo+!hzm!>a.txt&findstr /i /v "[a-z]:" a.txt>nul 2>nul后为什么又正常,还有待研究。
所谓的“正常”其实是不正常的。估计你和我一样,之前测试的时候只是测试了拖一个文件到cmd窗口上,而没有测试手动乱输一些。刚才测试了一下发现其实“findstr /i /v "[a-z]:" a.txt>nul 2>nul”这一句命令是执行失败的,这里的失败导致批处理跳到"||"后面继续执行下面的命令。这就是为什么在拖文件到cmd窗口上时显示出来的结果都是“正常”的。它就相当于直接忽略了“echo+!hzm!>a.txt&findstr /i /v "[a-z]:" a.txt>nul 2>nul”这一句的判断。
至此所有的问题都清楚了。真的很感谢各位的不吝赐教。
作者: zqz0012005    时间: 2009-7-5 10:04     标题: 回复 8楼 的帖子

是的,上次没有进一步测试。
其实去掉cls和>nul 2>nul就能看到错误提示了。




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