31

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?

Melebius
  • 6,183
  • 4
  • 39
  • 52
arathorn
  • 2,098
  • 3
  • 20
  • 29

4 Answers4

28
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 :-)

Joey
  • 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
11

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%\..\
Anders
  • 97,548
  • 12
  • 110
  • 164
5

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
Daniel Haley
  • 51,389
  • 6
  • 69
  • 95
Benilda Key
  • 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
0

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
Dmitry Sokolov
  • 3,118
  • 1
  • 30
  • 35