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

我今天发现 pushd和popd指令还受变量延迟的影响
比如v目录的v.bat文件内的代码是
  1. pushd %~dp0
  2. md tesst1
  3. cd tesst1
  4. md tesst2
  5. cd tesst2
  6. setlocal enabledelayedexpansion
  7. cd \
  8. popd
  9. popd
  10. popd
  11. popd
复制代码
然后打开cmd,以v目录所在的目录为工作目录,对v\v.bat 进行call指令
  1. call v\v.bat
复制代码
可以看到,不管popd了几次,最终目录都会是setlocal前所cd的目录,而不是初衷的v目录所在的目录

解决办法是在popd之前进行endlocal,比如:
  1. pushd %~dp0
  2. md tesst1
  3. cd tesst1
  4. md tesst2
  5. cd tesst2
  6. setlocal enabledelayedexpansion
  7. cd \
  8. endlocal
  9. popd
  10. popd
  11. popd
  12. popd
复制代码
如果有错误,还请达人们指教~~

我上面的操作过程写得有点繁琐,我来个一次性的代码吧:
  1. @echo off
  2. set a=tess2
  3. echo 调用前的工作目录(初始目录)是%~dp0
  4. ::接下来配置实验环境,可无视
  5. md yy>nul 2>nul
  6. >show.txt echo 现在的工作目录是yy目录“%~dp0yy”,不是初始目录,请尝试修改%a%.bat,在popd前插入endlocal语句,保存后再重新执行本批处理
  7. move show.txt yy>nul
  8. >show.txt echo 现在的工作目录是初始目录”%~dp0”,现在popd的效果正是所预期的
  9. if not exist %a%.bat (
  10.   >%a%.bat (
  11.   echo pushd %%~dp0
  12.   echo cd yy
  13.   echo setlocal enabledelayedexpansion
  14.   echo.
  15.   echo popd
  16.   )
  17. )
  18. ::以上为实验环境配置,可无视
  19. echo 调用初始目录下的%a%.bat (pushd → cd yy → popd)
  20. call %a%.bat
  21. ::调用%a%.bat后,若显示初始目录,那就对了;若显示yy目录,那么popd就失去初衷了
  22. echo %a%.bat执行结束
  23. echo 调用结束后,执行type show.txt,结果是:
  24. echo.
  25. type show.txt
  26. echo.
  27. pause
复制代码
1

评分人数

    • CrLf: 新发现技术 + 1

TOP

本帖最后由 zzpsongs 于 2012-8-6 13:25 编辑

回复 7# Hello123World


    是这样的,你如果用cmd直接调用你的第一个代码,会发现在pause后(即是退出该批处理,或者说,在调用时,不要添加pause),目录会改变到setlocal 之前所设置的,而非原来调用该批处理的启动目录;
如果在popd前添加endlocal则可避免这种现象。

TOP

回复 8# CrLf


    在下的意思是,如果不添加endlocal,popd的结果确实是启动目录,但是退出批处理后,目录却是setlocal之前所cd的。

TOP

本帖最后由 zzpsongs 于 2012-8-6 14:35 编辑

回复 11# CrLf


    是的,在下正是这个意思,也就是说,调用另一个批处理后要注意工作目录是否已被改变,而不是popd了,就放心了。

不过,这是什么道理呢?

TOP

返回列表