gpt4 book ai didi

windows - 批处理退出时隐含 "popd"

转载 作者:行者123 更新时间:2023-12-05 01:05:04 25 4
gpt4 key购买 nike

有没有办法在脚本末尾撤消所有 pushd。我所拥有的是:

pushd somwhere
rem doing stuff
goto end

:end
popd
goto :EOF

我想要的是:

setlocal
pushd somwhere
rem doing stuff
goto :EOF

但这不起作用,目录保持“pushd”。另一种我不能说会发生多少 pushd 的尝试是:

set CurrentDir=%CD%
rem doing a lot of pushd and popd
pushd somwhere

:POPBACK
if /i not "%CD%" == "%CurrentDir%" popd & goto POPBACK

但这看起来我很容易被 :POPBACK 卡住。添加一个计数器以退出该循环有点不确定我最终会在哪个目录。

在这种情况下,我想知道是否可以看到推送目录的堆栈。我发现的唯一内容是 prompt $P$+$G 中的 $+ ,它为每个 pushd 目录添加了一个“+”,例如D:\CMD++>。但我看不出如何利用它。

编辑:我刚刚注意到 prompt$+ 有问题,这让我很困惑。上例中的setlocal实际上是让脚本返回到初始目录,但是提示显示一个'+'表示缺少popd

D:\CMD>test.cmd
D:\CMD>prompt $P$+$g
D:\CMD>setlocal
D:\CMD>pushd e:\DATA
e:\DATA+>goto :EOF
D:\CMD+>popd
D:\CMD>

编辑:由于提示本地环境和目录堆栈之间的差异,我扩展了上面的示例表单,在调用脚本之前推送到 C:\DATA。脚本返回到从 (C:\DATA) 调用它的位置。到目前为止,一切都很好。第一个 popd 没有显示任何效果,因为它从堆栈中删除了最后一个 pushd 但不更改目录,因为目录更改已被(隐式)endlocal 撤消。第二个popd按预期返回到初始目录。

D:\CMD>pushd C:\DATA
C:\DATA+>d:\cmd\test.cmd
C:\DATA+>prompt $P$+$g
C:\DATA+>setlocal
C:\DATA+>pushd e:\DATA
e:\DATA++>goto :EOF
C:\DATA++>popd
C:\DATA+>popd
D:\CMD>

最佳答案

pushd command不带任何参数列出目录堆栈的内容,可以通过使用 output redirection > 编写列表来使用它。到一个(临时)文件,然后由 for /F loop 读取,并确定有多少 popd commands是必须的。

中:

pushd > "tempfile.tmp" && (
for /F "usebackq delims=" %%P in ("tempfile.tmp") do popd
del "tempfile.tmp"
)

直接在 :

pushd > "tempfile.tmp" && (for /F "usebackq delims=" %P in ("tempfile.tmp") do @popd) & del "tempfile.tmp"

注意,您不能使用 for/F "delims="%P in ('pushd') do ( ... ),因为 for /F将在 cmd.exe 的新实例中执行 pushd ,它有自己的新 pushd/popd 堆栈。


防止 pushd/popd 堆栈残留的一种方法是简单地避免 pushd 并使用 cd /D而是在本地化环境中(通过 setlocal/endlocal 在批处理文件中),因为与 popd 不同,endlocal 会在必要时隐式执行(即使批处理文件包含导致中止执行的 fatal error 的错误语法,例如 rem %~)。这当然只在没有 UNC 路径需要处理(即映射到本地路径)时才有效。


建议仅在没有任何分支的有限代码段中使用 pushd/popd(通过 ifgoto 等)。此外,请确保考虑潜在错误(在此处使用 conditional execution):

rem // First stack level:
pushd "D:\main" && (
rem // Second stack level:
pushd "D:\main\sub" && (
rem /* If `D:\main\sub` does not exist, `pushd` would obviously fail;
rem to avoid unintended `popd`, use conditional execution `&&`: */
popd
)
rem // We are still in directory `D:\main` here as expected.
popd
)

关于windows - 批处理退出时隐含 "popd",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71045685/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com