Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/batch-file/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Batch file CD环境变量何时更新?_Batch File_Cmd - Fatal编程技术网

Batch file CD环境变量何时更新?

Batch file CD环境变量何时更新?,batch-file,cmd,Batch File,Cmd,通常会发布使用批处理脚本中的CD环境变量获取当前工作目录的技巧。但是CD在调用另一个批处理文件时不会得到更新。然后,cd命令会回显另一批处理文件的新路径,但%cd%(或!cd!)不会更新。例如: @echo off cd %~dp0 echo in %0: CD=%CD% pause call X:\testcall.cmd 将其保存为C:\testcall.cmd和X:\testcall.cmd,然后运行C:\testcall.cmd。您应该看到CD的值没有改变。这似乎不依赖于调用;

通常会发布使用批处理脚本中的
CD
环境变量获取当前工作目录的技巧。但是
CD
在调用另一个批处理文件时不会得到更新。然后,
cd
命令会回显另一批处理文件的新路径,但
%cd%
(或
!cd!
)不会更新。例如:

@echo off
 cd %~dp0
 echo in %0: CD=%CD%
 pause
 call X:\testcall.cmd
将其保存为
C:\testcall.cmd
X:\testcall.cmd
,然后运行
C:\testcall.cmd
。您应该看到
CD
的值没有改变。这似乎不依赖于
调用
;以下工程均不适用:

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

…假设cmd.exe仅在该变量尚未设置时设置
CD
。是否正确?

诊断

您已经在某个点显式地设置了
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>
然后使用(例如)
%SCRIPT\u DIR%\config.txt“
引用该目录中的文件

或者,如果希望依赖当前目录,请使用
cd/d%~dp0
%cd%
是当前目录,而
%~dp0
是当前运行脚本的目录(带有尾随“\”)

另外,不要设置环境。var称为
CD
,因为它将覆盖默认的%CD%伪var,并且会令人难以置信地困惑-请参阅

例如,运行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

您可以将
%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>


使用脚本目录
%~dp0
可以解决问题,但通常不是。这样做效果更好:

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

set/P CD=

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

test1.bat-位于C:\temp

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

C:\temp启动test1时,输出为

File C:\temp\test1.bat CD=C:\temp 
File X:\test2.bat CD=C:\temp
结果绝对正确

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

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


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

CD
未明确设置。当cmd最初设置时,它也将保持其值。关键可能是你所说的:
CD
从未被M$真正实现过。因此,
set CD=%~dp0
似乎是解决方案,因为
CD
是一个标准变量,我发现一般来说,为同样的事情引入另一个变量会使问题变得复杂。当你在一个(更大的)脚本中看到像
SCRIPT\u DIR
这样的变量时,你总是想知道它是如何设置的,在哪里设置的;对于
CD
而言,其含义是固有的。@AndreasSpindler,您似乎认为工作目录和脚本目录是同一件事——它们根本不是同一件事。如果%CD%未反映当前工作目录,则表示它已由当前脚本、以前运行的另一个脚本或调用进程显式设置。另外,CD和SCRIPT_DIR(或%%dp0)的含义并不相同。SCRIPT_DIR或%dp0将是脚本文件的位置。CD是当前工作目录,可能不相同。@AndreasPindler:设置CD变量的值是一个非常糟糕的主意。想一想,如果有人试图设置日期或时间变量的值,会发生什么情况。你的想法的答案是:是的,所有这些变量都是同一类型的+1、好建议。但请注意,如果从UNC路径名(\\myserver\myshare\myfile.bat)运行批处理文件,则cd/d%~dp0将无法工作。改为使用pushd,它将为UNC路径创建一个临时驱动器号。@Aacine:Setting
DATE
将不正确;但是不更新
CD
,这难道不是一个bug吗?如果您看到代码中使用了
CD
,您不希望它返回当前工作目录吗?至少开箱即用的行为是不可理解的;在批处理文件之间来回分支时,依赖
CD
可能会很危险。
%=c:
不包含真正的当前目录,它只包含驱动器c:的当前目录,
%=d:%
包含驱动器d:的当前目录。所以你不知道哪个是真正的电流驱动是的,你完全正确。编辑了我的答案。每个卷都有自己的“当前目录”。如果设置了
%=X:
目录,则无法重命名该目录。它是在第一次访问卷时设置的。在调用方批处理或被调用批处理中,在哪里回显
%CD%
?如果使用
set CD=…
显式设置
CD
,则无法访问伪变量
CD
C:\OldDir>type script.bat
setlocal
cd c:\newdir

C:\OldDir>script

C:\OldDir>setlocal

C:\OldDir>cd c:\newdir

C:\OldDir>
cd >tmpfile
set /P CD= <tmpfile
del tmpfile
@echo off
cd %~dp0
echo File %~f CD=%CD%
call X:\test2.bat
@echo off
cd %~dp0
echo File %~f CD=%CD%
File C:\temp\test1.bat CD=C:\temp 
File X:\test2.bat CD=C:\temp