标题: [系统相关] 【已解决】不及时关闭延迟变量可能会导致 cd /d 操作失效 [打印本页]
作者: aloha20200628 时间: 2025-1-8 18:42 标题: 【已解决】不及时关闭延迟变量可能会导致 cd /d 操作失效
近期回帖中遭遇一则怪相,在win8.1,win10系统可复现,用以下5段示例代码说明,唯独其中第5段代码中最后的 cd /d "c:\temp\" 失效,即脚本退出后当前目录仍是 "c:\temp\xxx"
以下测试代码存为 test.bat 可在命令行直接用 test.bat n 来测试各段代码运行之后当前目录的结果,其命令行参数 n=1-5
- @echo off &if "%~1"=="" (goto :5) else goto :%~1
-
- :1
- setlocal enabledelayedexpansion
- cd "c:\temp\xxx"
- echo,!cd!
- cd "c:\temp\"
- echo,改变当前目录有效》!cd!
- endlocal
- exit/b
-
- :2
- setlocal enabledelayedexpansion
- cd "c:\temp\xxx"
- echo,!cd!
- cd "c:\temp\"
- echo,改变当前目录有效》!cd!
- endlocal
- exit/b
-
- :3
- setlocal enabledelayedexpansion
- cd "c:\temp\xxx"
- echo,!cd!
- endlocal
- cd "c:\temp\"
- echo,改变当前目录有效》%cd%
- exit/b
-
- :4
- cd "c:\temp\xxx"
- setlocal enabledelayedexpansion
- echo,!cd!
- endlocal
- cd "c:\temp\"
- echo,改变当前目录有效》%cd%
- exit/b
-
- :5
- cd /d "c:\temp\xxx"
- setlocal enabledelayedexpansion
- echo,!cd!
- cd /d "c:\temp\"
- echo,!cd!》当前显示有效》脚本退出后无效
- endlocal
- exit/b
复制代码
作者: Five66 时间: 2025-1-9 15:07
看不懂 ,看起来像cd跟cd /d的区别 , cd不受endlocal影响 而 cd /d受endlocal影响???
反正不知道endlocal对内建变量的处理方式 , 基本上不会分开来用或者依赖endlocal之后的值 , 随便了
作者: aloha20200628 时间: 2025-1-9 15:49
本帖最后由 aloha20200628 于 2025-1-9 15:50 编辑
回复 2# Five66
以前很多有关 cd 或 chdir 操作失效的原因概因未用 cd /d 参数,但本帖所谓的 cd /d 失效是与 setlocal enabeldelayedexpansion ... endlocal 有关,即一楼第五段代码运行后所示的 ‘怪状’ 》代码退出后当前目录并未被刚才调用过的 cd /d ... 操作有效改变...
作者: 77七 时间: 2025-1-9 16:29
- SETLOCAL /?
- 开始批处理文件中环境改动的本地化操作。在执行 SETLOCAL 之后
- 所做的环境改动只限于批处理文件。要还原原先的设置,必须执
- 行 ENDLOCAL。达到批处理文件结尾时,对于该批处理文件的每个
- 尚未执行的 SETLOCAL 命令,都会有一个隐含的 ENDLOCAL 被执行。
复制代码
区域环境
作者: aloha20200628 时间: 2025-1-9 16:51
回复 4# 77七
开关延迟变量的进退或生死变化应该是针对 !var! 变量吧,cd /d "c:\temp" 可是一个采用字面量(既非!var!亦非%var%)重置当前目录的实实在在的操作啊 ...
作者: 77七 时间: 2025-1-9 17:36
回复 5# aloha20200628
setlocal enabledelayedexpansion 给它起个全名 区域环境和延迟变量扩展,貌似我们平时都只是 简单的说 延迟变量扩展,只强调了它的一个作用。
作者: flashercs 时间: 2025-1-9 19:41
本帖最后由 flashercs 于 2025-1-9 19:51 编辑
- :1
- echo beforelocal cd=%cd%
- setlocal enabledelayedexpansion
- cd "c:\asp\abc"
- echo,setlocal cd=!cd!
- cd "c:\asp\"
- echo,改变当前目录有效》!cd!
- endlocal
- echo,endlocal cd=%cd%
- exit /b
-
- :5
- cd /d "c:\asp\abc"
- echo beforelocal cd=%cd%
- setlocal enabledelayedexpansion
- echo,setlocal cd=!cd!
- cd /d "c:\asp\"
- echo,setlocal cd=!cd!》当前显示有效》脚本退出后无效
- endlocal
- echo,endlocal cd=%cd%
- exit /b
复制代码
endlocal cd始终等于beforelocal cd,没问题.
另一个脚本调用这个cdtest.bat- @echo off
- cmd /c cdtest.bat 5
- echo,cmd /c cd=%cd%
- @REM call cdtest.bat 5
- @REM echo,call cd=%cd%
- pause
复制代码
cmd /c 与 call 脚本是有区别的.cmd /c 创建新的cmd进程,call 不会创建新cmd进程
作者: aloha20200628 时间: 2025-1-9 20:53
本帖最后由 aloha20200628 于 2025-1-9 21:20 编辑
谢谢诸位跟帖讨论 回到问题的焦点,还是用以下代码说明吧...- @echo off
- cd /d "c:\temp\xxx"
- setlocal enabledelayedexpansion
- echo,!cd!
- cd /d "c:\temp\"
- echo,!cd!》改变当前目录有效
- ::以下两式会如实 ‘列表然后删除 "c:\temp\*.txt" 文件’
- dir /b/a-d *.txt
- del /q *.txt
- endlocal
- :: 以下的操作不能想当然地认为当前目录还是 "c:\temp"
- echo,%cd%》自动复原为开启延迟变量前的当前目录
- exit/b
复制代码
可见》开启延迟变量后,无论 cd /d ... 或 dir /b/a-d ... 或 del ... 等操作结果都是如期而至,但关闭延迟变量后,当前目录会自动复原为开启延迟变量前的位置(但被删除的文件却是真的一去不复返了),有点出乎所料吧(先知先觉者除外 )以此为鉴,如从第10行之后续写代码时须谨记 ‘当前目录已被自动复原到开启延迟变量前的位置’...
作者: buyiyang 时间: 2025-1-9 21:42
可从源代码中窥见,本地化时当前目录、环境变量、命令扩展状态都会保存到当前批处理的数据结构体中,结束本地化还原。- // setlocal保存环境(省略简化、注释)
- struct envdata *CopyEnv() ;
- struct batsaveddata *p;
- p->dircpy = mkstr(mystrlen(CurDrvDir)*sizeof(TCHAR)+sizeof(TCHAR)) ;
- mystrcpy(p->dircpy, CurDrvDir) ; // 保存当前目录
- p->envcpy = CopyEnv() ; // 保存当前环境变量
- p->fEnableExtensions = fEnableExtensions; // 保存当前命令扩展的启用状态
- CurBat->saveddata[CurBat->numsavedenv] = p; // 保存为当前索引批处理数据结构
- CurBat->numsavedenv += 1; // 索引递增
-
- // endlocal恢复环境(省略简化、注释)
- bdat->numsavedenv -= 1; // 索引递减
- p = bdat->saveddata[bdat->numsavedenv];
- if (p) {
- // 如果当前盘与保存的盘符不同,则更改磁盘
- if (CurDrvDir[0] != (TCHAR)(c = _totupper(*p->dircpy)))
- ChangeDrive(c - (TCHAR) 0x40) ;
- ChangeDir(p->dircpy) ; // 恢复保存的目录
- ResetEnv(p->envcpy) ; // 恢复保存的环境变量
- fEnableExtensions = p->fEnableExtensions; // 恢复保存的命令扩展状态
- bdat->saveddata[bdat->numsavedenv] = NULL ;
- } ;
复制代码
作者: aloha20200628 时间: 2025-1-9 23:04
本帖最后由 aloha20200628 于 2025-1-9 23:05 编辑
回复 9# buyiyang
欢迎光临 批处理之家 (http://bbs.bathome.net/) |
Powered by Discuz! 7.2 |