在最后一个参数中的正斜杠导致批文件(“%〜dp0”)目录的path改变

我正在学习如何处理批处理脚本中的参数,并最终创build了一些用于读取参数和设置参数的模板

@echo off SetLocal EnableDelayedExpansion set needextra= set errstat= set noflag= set param_f=Not set yet set param_g=You didn't use G-flag :readARGS IF [%1] == [] goto :endARGS call :arg_%1 2> nul IF ERRORLEVEL 1 call :arg_default %1 SHIFT IF DEFINED needextra ( set %needextra%=%~1 SHIFT set needextra= ) goto :readARGS :endARGS echo path to directory of batch script: %~dp0 echo - noflag: !noflag! echo - param_f: !param_f! echo - param_g: !param_g! EndLocal exit /b 0 

打印目录的第一个回显对于我的问题是很重要的(见后面)之后,我为每个标志( arg_/flag )创build一个函数,另一个为没有标志( arg_default )的参数创build一个函数:

 :arg_/f -- flag f: set param_f to value of next argument set needextra=param_f exit /b 0 :arg_/g -- flag g: just set the param_g to a value set param_g=You used the G-flag exit /b 0 :arg_default -- default, neither flag f or g: just set the noflag echo noflag=%~1 exit /b 0 

当我把所有东西都放在一个batch file中时,让我们说C:\Users\user\scripts\params.bat然后把目录放在path中,我可以执行这个脚本:

 > params "just an arg" path to directory of batch script: C:\Users\user\scritpts\ - noflag: just an arg - param_f: Not set yet - param_g: You didn't use G-flag > params another /G /F "this is f" path to directory of batch script: C:\Users\user\scritpts\ - noflag: another - param_f: this is f - param_g: You used the G-flag 

事实上,我把它放在函数中允许我以任何顺序input参数,但是如果我把G标记作为最后一个我得到这个奇怪的行为:

 > params /F "this is f again" bizar /G path to directory of batch script: C:\ - noflag: bizar - param_f: this is f again - param_g: You used the G-flag 

%~dp0只返回C:\ ! 我用其他参数试了一下,把batch file移动到另一个目录下,在目录中调用它, %~dp0只返回C:\ 。 实际上,每当最后一个参数包含“/”时, %~dp0就会像这个例子一样“奇怪”

 > params /G /F stranger "what happens /here" path to directory of batch script: C:\Users\user\script\what happens \ - noflag: what happens /here - param_f: stranger - param_g: You used the G-flag 

有人可以解释我为什么发生这种情况吗? 我无法弄清楚为什么,也找不到networking上的任何东西。 我使用Windows 10

我真的很感激你可以提供任何帮助。

Solutions Collecting From Web of "在最后一个参数中的正斜杠导致批文件(“%〜dp0”)目录的path改变"

之所以这样

 params "just an arg" params another /G /F "this is f" 

作品和这个

 params /G /F stranger "what happens /here" params /F "this is f again" bizar /G 

不工作是…在这两种情况下,它不工作!

正如Magoo指出的那样,你的问题是shift命令。 默认情况下,它移动所有的参数,所以第十个参数存储在%9 ,旧的%9存储在%8%1存储在%0 ,失去了对当前批处理文件的引用。

在你的代码中,你正在移动所有的参数,直到全部被处理。 这留下了%0里面的最后一个参数,在这个时候事情变得有趣了。

当请求%~dp0 ,最后一个参数存储在%0并且当我们要求参数内部引用的元素的驱动器和文件夹时, cmd尝试解析它,假设你知道你要求的内容,而变量包含对文件系统中元素的有效引用,将其转换为绝对路径,然后检索请求的元素。

在这里你遇到了两个例子

  • %0只包含一个没有斜杠或反斜杠的简单字符串。 cmd其作为存储在当前活动目录中的文件名进行处理,因此,当您请求驱动器和路径时,将检索当前活动目录的驱动器和路径。 在你结束的“工作”情况下
 "C:\Users\user\script\just an arg" -> %~dp0 = "C:\Users\user\script\" "C:\Users\user\script\this is f" -> %~dp0 = "C:\Users\user\script\" 
  • %0包含一个带有斜线或反斜线的字符串。 这是相同的情况之前,但字符串包含一个相对路径(第一个失败的情况下),前缀与当前的活动目录或从根文件夹路径(第二个失败的情况下),所以你结束
 "C:\Users\user\script\what happens /here" -> %~dp0 = "C:\Users\user\script\what happens " "C:/g" -> %~dp0 = "C:\" 

你怎么解决它?

解决这个问题的最简单方法可能是,如Magoo所提议的,在进行任何参数移位之前,保存%0参数的值。

另一个选择是将shift命令改变为shift /1 ,以表明换档将从第一个参数开始,使%0保持不变。

如果没有这个选项可以使用,你仍然可以从一个子程序中检索批处理文件的引用

 @echo off setlocal enableextensions disabledelayedexpansion rem Ensure %0 is discarded shift echo %0 call :getCurrentBatchFolder dp0 echo %dp0% exit /b :getCurrentBatchFolder returnVar set "%~1=%~dp0" goto :eof 

我建议在SHIFT命令后%~d0很可能是不可靠的,所以我会在开始时保存它的值。

也许这个问题可能是有帮助的。 我仍然保存~dp0但…