I'd like to get the parent directory of a file from within a .bat
file. So, given a variable set to "C:\MyDir\MyFile.txt"
, I'd like to get "C:\MyDir"
. In other words, the equivalent of dirname()
functionality in a typical UNIX environment. Is this possible?
-
1I added a remark about file names with spaces; forgot to test with those. – Joey Apr 22 '09 at 17:40
4 Answers
for %%F in (%filename%) do set dirname=%%~dpF
This will set %dirname%
to the drive and directory of the file name stored in %filename%
.
Careful with filenames containing spaces, though. Either they have to be set with surrounding quotes:
set filename="C:\MyDir\MyFile with space.txt"
or you have to put the quotes around the argument in the for
loop:
for %%F in ("%filename%") do set dirname=%%~dpF
Either method will work, both at the same time won't :-)

- 344,408
- 85
- 689
- 683
-
I think you mean, "put the *quotes* around the argument in the for loop:" – aphoria Apr 22 '09 at 18:57
-
@mosh, what is the expected result for a hardlink? Also note that your workarounds is sensitive to Unicode file names and the console font. – Joey Jul 09 '16 at 10:37
If for whatever reason you can't use FOR (no Command Extensions etc) you might be able to get away with the ..\ hack:
set file=c:\dir\file.txt
set dir=%file%\..\

- 97,548
- 12
- 110
- 164
-
This solution (cd /d file\..) works better in win7, The other solution fails sometimes in win7 %%~dpF. – mosh Oct 15 '15 at 12:50
-
The problem with the for loop is that it leaves the trailing \ at the end of the string. This causes problems if you want to get the dirname multiple times. Perhaps you need to get the name of the directory that is the grandparent of the directory containing the file instead of just the parent directory. Simply using the for loop technique a second time will remove the \, and will not get the grandparent directory.
That is you cannot simply do the following.
set filename=c:\1\2\3\t.txt
for %%F in ("%filename%") do set dirname=%%~dpF
for %%F in ("%dirname%") do set dirname=%%~dpF
This will set dirname to "c:\1\2\3", not "c:\1\2".
The following function solves that problem by also removing the trailing \.
:dirname file varName
setlocal ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION
SET _dir=%~dp1
SET _dir=%_dir:~0,-1%
endlocal & set %2=%_dir%
GOTO :EOF
It is called as follows.
set filename=c:\1\2\3\t.txt
call :dirname "%filename%" _dirname
call :dirname "%_dirname%" _dirname

- 51,389
- 6
- 69
- 95

- 2,836
- 1
- 22
- 34
-
Good solution for the trailing \ problem. Otherwise one can't use the `"%dirname%"` directly since the ending quote would be escaped by the preceding slash. In such a case the `"%dirname%\"` works. But only either of them at a time. – Vertigo Jun 20 '17 at 17:48
To get rid of the trailing \
just pass the result %~dpA
+.
into the next for
and get the full path %~fB
:
C:\> @for /f "delims=" %A in ("c:\1\2\3\t.txt") do @for /f "delims=" %B in ("%~dpA.") do @echo %~fB
c:\1\2\3
C:\> @for /f "delims=" %A in ("c:\1\2\3\t 1.txt") do @for /f "delims=" %B in ("%~dpA.") do @echo %~fB
c:\1\2\3
C:\> @for /f "delims=" %A in ("c:\1\2\3 3\t 1.txt") do @for /f "delims=" %B in ("%~dpA.") do @echo %~fB
c:\1\2\3 3

- 3,118
- 1
- 30
- 35