3

通常发布使用CD批处理脚本中的环境变量来获取当前工作目录的提示。但是在输入另一个批处理文件CD时不会更新。call然后该cd命令回显另一个批处理文件的新路径,但%CD%(或!CD!)未更新。例子:

@echo off
 cd %~dp0
 echo in %0: CD=%CD%
 pause
 call X:\testcall.cmd

将此另存为C:\testcall.cmdand X:\testcall.cmd,然后运行C:\testcall.cmd​​. 您应该看到 的值CD没有改变。这似乎不依赖于call; 以下均无效:

start /D <NEW_DIR> <OTHER_CMD_FILE>
start cmd /c <NEW_DIR>\<OTHER_CMD_FILE>
cmd /c <NEW_DIR>\<OTHER_CMD_FILE>
<NEW_DIR>\<OTHER_CMD_FILE>
cd %~dp0
pushd %~dp0

CD将保留它的旧值,而cd(命令)显示正确的目录。因此我CD在脚本的开头设置:

set CD=%~dp0

...虽然假设cmd.exe仅在此变量尚未设置CD时才设置。真的?

4

5 回答 5

7

%CD%当前目录%~dp0而是当前正在运行的脚本的目录(带有尾随'\')。

另外,不要设置环境。var 调用CD,因为它会覆盖默认的 %CD% 伪变量,并且会令人难以置信地混淆 - 请参阅OldNewThing - ERRORLEVEL is not %ERRORLEVEL%

例如,运行 c:\temp\a.cmd 时,即:

@echo off
echo Currently running script: %~dpnx0
cd %~dp0
echo scriptDir=%~dp0, CD=%CD%
cd %~dp0a
echo scriptDir=%~dp0, CD=%CD%
set CD=bogus value
echo scriptDir=%~dp0, CD=%CD%

输出:

Currently running script: c:\temp\a.cmd
scriptDir=c:\temp\, CD=c:\temp
scriptDir=c:\temp\, CD=c:\temp\a
scriptDir=c:\temp\, CD=bogus value
于 2013-04-29T12:19:18.230 回答
4

诊断

您在某些时候CD明确设置了变量。如果您这样做,它将不再自动反映当前工作目录。要撤消此操作,请将其设置为空:

set CD=

然后它将再次开始工作。

为什么是这样?好吧,自动 CD 变量是作为一项功能引入的。我假设他们只是不想破坏已经使用该变量名称的预先存在的脚本。因此,如果您明确设置它,CMD 将假定您是故意这样做的。

讨论

首先,如果父进程有一个显式设置的CD变量,它将被子进程继承。

另一方面,您不应该期望其中任何一个更新%CD%父进程的值:

start /D <NEW_DIR> <OTHER_CMD_FILE>
start cmd /c <NEW_DIR>\<OTHER_CMD_FILE>
cmd /c <NEW_DIR>\<OTHER_CMD_FILE>

这些都创建了新进程,然后新进程更改了自己的工作目录。您不应期望这会影响父进程。

最后一个,根本不更新工作目录,除非 OTHER_CMD_FILE 执行 CD 命令:

<NEW_DIR>\<OTHER_CMD_FILE>

仅仅因为您在不同的目录中执行了脚本并不意味着脚本的工作目录会改变。脚本工作目录不必设置为脚本的位置。

建议

依赖工作目录被设置为任何特别的东西通常是一个坏主意。

你可能想要这样的东西:

SET SCRIPT_DIR=%~dp0

然后使用(例如)"%SCRIPT_DIR%\config.txt"来引用该目录中的文件。

或者,如果您希望依赖当前目录,请使用cd /d %~dp0

于 2013-04-29T12:18:55.610 回答
2

您可以将%cd%变量设置为您想要的任何值,驱动器的实际当前目录C:存储在%=c:%变量中,您不能使用以下set命令更改它:

@echo off
echo Currently running script: %~dpnx0
cd %~dp0
echo scriptDir=%~dp0, CD=%CD%
set CD=bogus value
echo scriptDir=%~dp0, CD=%CD%, =c:=%=c:%
set =c:=bogus value
echo scriptDir=%~dp0, CD=%CD%, =c:=%=c:%

输出是:

Currently running script: C:\OldDir\a.bat
scriptDir=C:\OldDir\, CD=bogus value
scriptDir=C:\OldDir\, CD=bogus value, =c:=C:\OldDir
syntax error.
scriptDir=C:\OldDir\, CD=bogus value, =c:=C:\OldDir

子进程的=C:变量始终从父进程设置。如果您setlocal在脚本中避免使用该命令或选择endlocal,则可以更改持久化当前 cmd 会话的当前目录:

C:\OldDir>type script.bat
cd c:\newdir

C:\OldDir>script

C:\OldDir>cd c:\newdir

C:\NewDir>

.

C:\OldDir>type script.bat
setlocal
cd c:\newdir

C:\OldDir>script

C:\OldDir>setlocal

C:\OldDir>cd c:\newdir

C:\OldDir>
于 2013-04-29T15:02:02.223 回答
2

我根据您的评论构建了两个批处理文件

test1.bat - 位于C:\temp

@echo off
cd %~dp0
echo File %~f CD=%CD%
call X:\test2.bat

test2.bat - 位于 * X:*

@echo off
cd %~dp0
echo File %~f CD=%CD%

C:\temp开始test1,输出为

File C:\temp\test1.bat CD=C:\temp 
File X:\test2.bat CD=C:\temp

结果绝对正确!

使用绝对或相对路径启动批处理文件(或任何其他程序)不会更改当前目录。

CD似乎出现故障,因为CD无法按照您使用它的方式更改驱动器。

您需要添加一个开关 CD /d %~dp0

于 2013-05-08T09:32:42.520 回答
0

使用脚本目录%~dp0可能是一种解决方案,但通常不是。这效果更好:

cd >tmpfile
set /P CD= <tmpfile
del tmpfile

该解与CD变量一致。CD 包含当前目录,如果不在当前驱动器的根目录中,则不以斜杠字符结尾。打印的路径cd正是如此。

我多年来一直在使用它,并且CD明确设置没有问题。后来我开始使用PWD(如在 Bash 中)。此变量在 MSDOS 中不保留。所以我的问题实际上是:“我们可以摆脱这些行,还是这是一些 MSDOS 习语?”

有些人写过CD明确的设置是不好的。为什么?MSODS 从未正确设计,也没有进一步开发。你可以用它做的任何事情都是合法的。没有糟糕的 MSDOS 编程——只有好的和坏的 hack。我知道没有其他语言在这种情况下这种观点是合法的。

于 2013-05-06T16:32:11.773 回答