What does %~dp0 mean, and how does it work?
Batch FileBatch File Problem Overview
I find %~dp0
very useful, and I use it a lot to make my batch files more portable.
But the label itself seems very cryptic to me... What is the ~
doing? Does dp
mean drive and path? Does the 0
refer to %0
, the path to the batch file that includes the file name?
Or it is just a weird label?
I'd also like to know if it is a documented feature, or something prone to be deprecated.
Batch File Solutions
Solution 1 - Batch File
Calling
for /?
in the command-line gives help about this syntax (which can be used outside FOR, too, this is just the place where help can be found).
> In addition, substitution of FOR
> variable references has been enhanced.
> You can now use the following optional
> syntax:
>
> %~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
>
> The modifiers can be combined to get
> compound results:
>
> %~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
>
> In the above examples %I and PATH can
> be replaced by other valid values.
> The % syntax is terminated by a valid
> FOR variable name. Picking upper case
> variable names like %I makes it more
> readable and avoids confusion with the
> modifiers, which are not case
> sensitive.
There are different letters you can use like f
for "full path name", d
for drive letter, p
for path, and they can be combined. %~
is the beginning for each of those sequences and a number I
denotes it works on the parameter %I
(where %0
is the complete name of the batch file, just like you assumed).
Solution 2 - Batch File
(First, I'd like to recommend this useful reference site for batch: http://ss64.com/nt/)
Then just another useful explanation: http://htipe.wordpress.com/2008/10/09/the-dp0-variable/
> # The %~dp0 Variable #
>
> The %~dp0
(that’s a zero) variable when referenced within a Windows
> batch file will expand to the drive letter and path of that batch
> file.
>
> The variables %0-%9
refer to the command line parameters of the batch
> file. %1-%9
refer to command line arguments after the batch file name.
> %0
refers to the batch file itself.
>
> If you follow the percent character (%
) with a tilde character (~
),
> you can insert a modifier(s) before the parameter number to alter the
> way the variable is expanded. The d
modifier expands to the drive
> letter and the p
modifier expands to the path of the parameter.
>
> Example: Let’s say you have a directory on C:
called bat_files
, and
> in that directory is a file called example.bat
. In this case, %~dp0
> (combining the d
and p
modifiers) will expand to C:\bat_files\
.
>
> Check out this Microsoft article for a full explanation.
>
> Also, check out this forum thread.
And a more clear reference from here:
-
%CmdCmdLine%
will return the entire command line as passed to CMD.EXE -
%*
will return the remainder of the command line starting at the first command line argument (in Windows NT 4, %* also includes all leading spaces) -
%~dn
will return the drive letter of %n (n can range from 0 to 9) if %n is a valid path or file name (no UNC) -
%~pn
will return the directory of %n if %n is a valid path or file name (no UNC) -
%~nn
will return the file name only of %n if %n is a valid file name -
%~xn
will return the file extension only of %n if %n is a valid file name -
%~fn
will return the fully qualified path of %n if %n is a valid file name or directory
ADD 1
Just found some good reference for the mysterious ~
tilde operator.
The %~
string is called percent tilde operator. You can find it in situations like: %~0
.
The :~
string is called colon tilde operator. You can find it like %SOME_VAR:~0,-1%
.
ADD 2 - 1:12 PM 7/6/2018
%1-%9
refer to the command line args. If they are not valid path values, %~dp1
- %~dp9
will all expand to the same value as %~dp0
. But if they are valid path values, they will expand to their own driver/path value.
For example: (batch.bat)
@echo off
@echo ~dp0= %~dp0
@echo ~dp1= %~dp1
@echo ~dp2= %~dp2
@echo on
Run 1:
D:\Workbench>batch arg1 arg2
~dp0= D:\Workbench\
~dp1= D:\Workbench\
~dp2= D:\Workbench\
Run 2:
D:\Workbench>batch c:\123\a.exe e:\abc\b.exe
~dp0= D:\Workbench\
~dp1= c:\123\
~dp2= e:\abc\
Solution 3 - Batch File
The variable %0
in a batch script is set to the name of the executing batch file.
The ~dp
special syntax between the %
and the 0
basically says to expand the variable %0
to show the drive letter and path, which gives you the current directory containing the batch file!
Help = Link
Solution 4 - Batch File
%~dp0 expands to current directory path of the running batch file.
To get clear understanding, let's create a batch file in a directory.
> C:\script\test.bat
with contents:
@echo off
echo %~dp0
When you run it from command prompt, you will see this result:
> C:\script\
Solution 5 - Batch File
Another tip that would help a lot is that to set the current directory to a different drive one would have to use %~d0
first, then cd %~dp0
. This will change the directory to the batch file's drive, then change to its folder.
Alternatively, for #oneLinerLovers, as @Omni pointed out in the comments cd /d %~dp0
will change both the drive and directory :)
Hope this helps someone.
Solution 6 - Batch File
Great example from Strawberry Perl's portable shell launcher:
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%
not sure what the negative 1's doing there myself, but it works a treat!
Solution 7 - Batch File
An example would be nice - here's a trivial one
for %I in (*.*) do @echo %~xI
it lists only the EXTENSIONS of each file in current folder
for more useful variable combinations (also listed in previous response) from the CMD prompt execute: HELP FOR
which contains this snippet
The modifiers can be combined to get compound results:
%~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