“%~dp0”是什么意思,它是如何工作的?

1256
我认为 %~dp0 非常有用,我经常使用它来使我的批处理文件更加便携。
但是这个标签本身对我来说似乎非常神秘...它是什么意思呢?~ 是在做什么?dp 指的是驱动器和路径吗?0 是否指代包含文件名称的批处理文件的路径 %0
还是说这只是一个奇怪的标签?
我也想知道它是否是一个被记录的特性,或者容易被弃用。

17
可能是这篇文章的重复内容。在Windows批处理文件中,%~d0表示批处理文件所在驱动器的字母。 - Helen
5
你是正确的,海伦。当我搜索 %dp0 时,那个问题没有出现。可能是因为它的标题上写的是 %d0 而不是 %~dp0。 - Sebastián Grignoli
12
SymbolHound非常适合搜索除字母数字字符以外的内容。例如,搜索“%〜dp0”。通常我发现排名靠前的结果与SO上的内容有关。 - DavidRR
SymbolHound在我使用http://symbolhound.com/?q=%25~dp0进行搜索时无法工作。然而,这个可以:https://www.google.com/search?q=%25~dp0 - 只是说一下... - Kristopher
2
SymbolHound 2019:无法工作,uMatrix 表明它连接到像 blockchain.info 和 paypalobjects.com 这样的第三方网站。 - Nils Lindemann
@Helen 我喜欢那个更早的答案,因为它有一个评论链接回到这个答案。♾ - ruffin
7个回答

955

调用

for /?

在命令行中使用该语法会显示帮助信息(该语法也可用于FOR以外的地方,这只是找到帮助的地方)。

此外,FOR变量引用的替换已经得到增强。 现在您可以使用以下可选语法:

%~I         - expands %I removing any surrounding quotes (")
%~fI        - expands %I to a fully qualified path name
%~dI        - expands %I to a drive letter only
%~pI        - expands %I to a path only
%~nI        - expands %I to a file name only
%~xI        - expands %I to a file extension only
%~sI        - expanded path contains short names only
%~aI        - expands %I to file attributes of file
%~tI        - expands %I to date/time of file
%~zI        - expands %I to size of file
%~$PATH:I   - searches the directories listed in the PATH
               environment variable and expands %I to the
               fully qualified name of the first one found.
               If the environment variable name is not
               defined or the file is not found by the
               search, then this modifier expands to the
               empty string

可以组合使用修饰符以获得复合结果:

%~dpI       - expands %I to a drive letter and path only
%~nxI       - expands %I to a file name and extension only
%~fsI       - expands %I to a full path name with short names only
%~dp$PATH:I - searches the directories listed in the PATH
               environment variable for %I and expands to the
               drive letter and path of the first one found.
%~ftzaI     - expands %I to a DIR like output line
在上述示例中,%I和PATH可以被其他有效值替换。 %~语法以有效的FOR变量名终止。选择如%I这样的大写变量名称可使其更易读,并避免与修饰符混淆,这些修饰符不区分大小写。您可以使用不同的字母,比如“f”代表完整路径名,“d”代表驱动器号,“p”代表路径,它们可以组合使用。%~是每个序列的开始,数字I表示它适用于参数%I(其中%0是批处理文件的完整名称,就像您所假设的那样)。

2
我不知道其他人怎么样,但是当我使用 I 时,会出现“在批处理参数替换中使用路径运算符的以下用法无效。要获取有效格式,请键入 CALL /? 或 FOR /? 命令的语法不正确。”的错误提示。我必须使用 0 而不是 I。我不知道是否有遗漏或其他问题,但只是想让大家知道。 - mythofechelon
91
@BenHooper,“I”是一个代替变量索引的占位符。“0”表示调用文件,“1”表示第1个参数,“2”表示第2个参数,以此类推... - Chris
12
这个答案很好,而且详尽。为了更简洁一些,我喜欢这个与之类似的问题的回答:https://dev59.com/X3VD5IYBdhLWcg3wBm5h - Frank N
2
这个答案有点令人困惑,因为这些替换可以在FOR之外使用。 - David
3
请注意,如果您使用Process.Start直接从C#运行批处理文件,则该批处理文件将将%~dp0扩展为C#程序的工作目录,而不是批处理文件的位置。 如果您使用Process.Start运行cmd.exe,然后再运行批处理文件(例如使用参数/C foo.bat),那么一切都很好。 我怀疑这与PATH的扩展方式和位置有关。 您可以设置进程的WorkingDirectory以解决此问题。 - yoyo

485

首先,我想推荐这个有用的批处理参考网站:http://ss64.com/nt/

然后再给出另一个有用的解释:http://htipe.wordpress.com/2008/10/09/the-dp0-variable/

%~dp0 变量

在 Windows 批处理文件中引用 %~dp0(注意是数字零)变量将扩展为该批处理文件的驱动器字母和路径。

变量 %0-%9 指的是批处理文件的命令行参数。而 %1-%9 则指的是批处理文件名后面的命令行参数。而 %0 则指的是批处理文件本身。

如果您在百分号字符 (%) 后跟着波浪线字符 (~),您可以在参数编号之前插入一个或多个修饰符,以更改变量扩展的方式。 d 修饰符会扩展为驱动器字母,p 修饰符则会扩展为该参数的路径。

例如:假设您在 C 盘上有一个名为 bat_files 的目录,并且该目录中有一个名为 example.bat 的文件。在这种情况下,%~dp0 (结合 dp 修饰符) 将扩展为 C:\bat_files\

请参阅 此 Microsoft 文章 获取完整说明。

另请参阅 此论坛帖子

这里有一份更清晰的参考资料:here

  • %CmdCmdLine%将返回传递给CMD.EXE的整个命令行

  • %*将返回从第一个命令行参数开始的剩余命令行(在Windows NT 4中,%*还包括所有前导空格)

  • %~dn将返回%n(n可以从0到9)的驱动器号,如果%n是有效的路径或文件名(无UNC)

  • %~pn将返回%n的目录,如果%n是有效的路径或文件名(无UNC)

  • %~nn将返回%n的文件名,如果%n是有效的文件名

  • %~xn将返回%n的文件扩展名,如果%n是有效的文件名

  • %~fn将返回%n的完全限定路径,如果%n是有效的文件名或目录

ADD 1

我找到了一些关于神秘的波浪符操作符~的好参考资料。

%~字符串被称为百分号波浪符操作符percent tilde,你可以在如下情况中找到它:%~0

:~字符串被称为冒号波浪符操作符colon tilde,你可以在如下情况中找到它:%SOME_VAR:~0,-1%

添加 2 - 1:12 PM 7/6/2018

%1-%9指的是命令行参数。如果它们不是有效的路径值,%~dp1 - %~dp9将扩展为与%~dp0相同的值。但如果它们是有效的路径值,它们将扩展为它们自己的驱动器/路径值。

例如:(batch.bat)

@echo off
@echo ~dp0= %~dp0
@echo ~dp1= %~dp1
@echo ~dp2= %~dp2
@echo on

运行1:

D:\Workbench>batch arg1 arg2

~dp0= D:\Workbench\
~dp1= D:\Workbench\
~dp2= D:\Workbench\

运行2:

D:\Workbench>batch c:\123\a.exe e:\abc\b.exe

~dp0= D:\Workbench\
~dp1= c:\123\
~dp2= e:\abc\

也对这个概念很好奇,在这里找到了很好的解释。谢谢Mingge。^_^ - Eugene
2
对我来说,它会扩展为 c:\bat_files\(带有尾部路径分隔符)。 - santa
微软文章和论坛主题的链接不再有效 :( - wovano
2
如果你提供相对路径,它们会被扩展为相对于当前目录的路径......在你的测试中,当前目录恰好与 %~dp0 相同。%~dp1 并不会像魔法般变成 %~dp0,只因为文件 arg1 不存在; 你可能希望你的批处理文件创建它! - DimeCadmium

176

批处理脚本中的变量%0被设置为正在执行的批处理文件的名称。

%0~dp之间的特殊语法基本上是扩展变量%0以显示驱动器号和路径,这给出了包含批处理文件的当前目录!

帮助 = 链接


@AndyпјҢжңүжІЎжңүеҠһжі•еңЁcmdдёӯзӣҙжҺҘжөӢиҜ•%0иҖҢдёҚеҝ…е°Ҷ.batж–Ү件дҝқеӯҳеҲ°жң¬ең°зЎ¬зӣҳпјҹ - Pacerier
链接已经失效了,我找不到正确的链接。一个待处理的编辑仍然包含着这个失效的链接。 - George

61

%~dp0可以展开为运行批处理文件的当前目录路径。

为了更好地理解,让我们在一个目录中创建一个批处理文件。

C:\script\test.bat

该批处理文件内容如下:

@echo off
echo %~dp0

当你从命令提示符中运行它时,你会看到以下结果:

C:\script\


43

另一个非常有用的提示是,如果要将当前目录设置为 不同的驱动器 ,则必须首先使用%~d0,然后使用cd %~dp0。这将更改目录到批处理文件所在的驱动器,然后更改到其文件夹。

或者,对于喜欢一行命令的人,就像@Omni在评论中指出的那样,cd /d %~dp0将同时更改驱动器和目录:)

希望这会帮助到某些人。


24
cd 命令有一个内置参数,可以同时切换驱动器和文件夹:cd /d %~dp0 - OmnipotentEntity
2
你说得对,/d参数很有用,但它应该作为一个备选答案而不是评论发布。非常感谢你指出这一点,我之前并不知道 :) - Marvin Thobejane
6
你也可以使用“pushd %~dp0”来切换驱动器和文件夹。该命令可以将当前目录压入一个堆栈,并切换到批处理文件所在的驱动器和文件夹。 - fmuecke

27

来自Strawberry Perl便携式shell启动器的优秀示例:

set drive=%~dp0
set drivep=%drive%
if #%drive:~-1%# == #\# set drivep=%drive:~0,-1%

set PATH=%drivep%\perl\site\bin;%drivep%\perl\bin;%drivep%\c\bin;%PATH%

我自己也不确定负1在那里的作用,但它确实起到了很好的效果!


11
+1 非常有用。if语句检查反斜杠是否存在并在必要时删除反斜杠。条件中的负数 1 提取最后一个字符,set语句中的表达式获取路径字符串减去最后一个字符(即反斜杠)。 - Matt
1
负1表示减去最后一个字符。阅读变量子字符串 - phuclv

13

提供一个示例会很好 - 这里有一个微不足道的示例

for %I in (*.*) do @echo %~xI

它仅列出当前文件夹中每个文件的扩展名

要从CMD提示符中执行更多有用的变量组合(也列在先前的响应中),请执行:HELP FOR,其中包含此片段

可以组合这些修改符以获得复合结果:

%~dpI       - expands %I to a drive letter and path only
%~nxI       - expands %I to a file name and extension only
%~fsI       - expands %I to a full path name with short names only
%~dp$PATH:I - searches the directories listed in the PATH
               environment variable for %I and expands to the
               drive letter and path of the first one found.
%~ftzaI     - expands %I to a DIR like output line

我得到了“~xI在这个时候是意外的。”尝试这个例子 - 是因为我使用的是Win 7吗? - chapter3
这是很好的信息,但它未能解决原始帖子的问题。 - De Shan Baptiste
@chapter3 ~xI~xl 或 L / Low = l 或 I / Low = **i**? - Io-oI

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接