在 BAT 文件中展开 `%~dp0` 后出现意外的重复目录名称

在 BAT 文件中展开 `%~dp0` 后出现意外的重复目录名称

我在 Windows 10 Enterprise x64 上。我有以下目录层次结构,最内层有一个 BAT 文件:

C:\
  dir\
    my files\
      run.bat

该 BAT 文件包含以下行:

@pushd %~dp0
@echo %~dp0
@popd

(含义和用法%~dp0在帮助主题中有解释for /?这个答案

如果我从当前目录为的命令提示符运行 BAT 文件C:\dir\my files,那么我会得到一个非常合理的结果:

C:\dir\my files>run.bat
C:\dir\my files\

但是如果我从父目录调用它C:\dir,我会得到:

C:\dir>"my files"\run.bat
C:\dir\my files\my files"\

"\嗯?请注意,最内层的目录名称重复了,并且末尾有一些零散的字符。让我们以不同的方式尝试一下:

C:\dir>"my files\run.bat"
C:\dir\my files\my files\

杂散字符消失了,但目录名称仍然重复。这该如何解释?如何修改 BAT 文件,以便无论从哪个目录调用它,它都会给出相同的输出?

当然,我的真实场景比这个简化版本更复杂。 的值%~dp0与其他字符串连接,分配给环境变量,作为参数传递给其他脚本等。

答案1

这是一个cmd.exe 中已知的错误/设计缺陷-%~dp0如果引用了批处理脚本的路径,则变体可能会给出错误的结果。

有一个解决方法。您可以可靠地从 CALLed 子程序中获取值(请注意,必须使用至少一个修饰符~d,如~f等,否则您将获得子程序:label

@echo off
setlocal
pushd %~dp0
echo From main fails: "%~dp0"
call :test
popd
exit /b

:test
echo From subroutine OK: "%~dp0"

-- 示例输出 --

d:\dir>"my files\test.bat"
From main fails: "d:\dir\my files\my files\"
From subroutine OK: "d:\dir\my files\"

答案2

作为一种解决方法,请预先存储目录:

set "dir=%~dp0"

这是因为%0实际上是被调用的路径(如argv参数 0),所以在您的示例中它是"my files"\run.bat"my files\run.bat"

当你这样做%~dp0,cmd.exe正在构建完整路径相对于当前目录然后提取您要求的部分。

在您之后pushd,“完整路径” ( %~f0) 将是:

C:\dir\my files\my files\run.bat
C:\dir\my files\my files"\run.bat

...然后修剪文件名以获取结果。

相关内容