22

I need to find the name of the parent directory for a file in DOS

for ex.

Suppose this is the directory

C:\test\pack\a.txt

I have a script which asks me the file name

C:\\>getname.bat     
enter file name: c:\test\pack\a.txt   

now the script should return just the parent name of the file.

pack           

and NOT the entire parent path to the file.

c:\test\pack   
Ross Ridge
  • 38,414
  • 7
  • 81
  • 112

10 Answers10

24

It can be very simple to get the parent folder of the batch file:

@echo off
for %%a in ("%~dp0\.") do set "parent=%%~nxa"
echo %parent%

And for a parent of a file path as per the question:

@echo off
for %%a in ("c:\test\pack\a.txt") do for %%b in ("%%~dpa\.") do set "parent=%%~nxb"
echo %parent%
foxidrive
  • 40,353
  • 10
  • 53
  • 68
  • 3
    I found this useful for finding a parent folder that was a couple directories above the batch file. Just add `\..` after the `%~dp0\.` to go up a folder level. Example: `for %%a in ("%~dp0\.\..\..\..") do set "parent=%%~nxa"` – Matt Nov 22 '17 at 02:18
  • Note for others: you may want `("%~p1\.")` instead of `("%~dp0\.")`. – Venryx Jun 02 '20 at 03:06
  • 2
    While academically interesting, this does not answer the OP's question. I'm in the same situation, running a batch file from `C:\A\B\C.Bat` which is processing a file `C:\D\E\Foo.txt` - I don't care about the path of the batch file itself, I care about getting `E` from the patch of the text file. – dgnuff Apr 27 '21 at 19:10
13

First answer above does not work if parent directory name contains a space. The following works:

@echo off
setlocal

set ParentDir=%~p1
set ParentDir=%ParentDir: =:%
set ParentDir=%ParentDir:\= %
call :getparentdir %ParentDir%
set ParentDir=%ParentDir::= %

echo ParentDir is %ParentDir%
goto :EOF

:getparentdir
if "%~1" EQU "" goto :EOF
Set ParentDir=%~1
shift
goto :getparentdir

Calling the above with parameter of "C:\Temp\Parent Dir With Space\myfile.txt" gives following:

>GetParentDir "C:\Temp\Parent Dir With Space\myfile.txt"
ParentDir is Parent Dir With Space

The above works by replacing spaces with colons (these should not exist in Windows paths), then replacing directory delimiters with spaces to so individual directories are passed to getparentdir as separate arguments. Function getparentdir loops until it finds its last argument. Finally any colons in result are replaced by spaces.

duncanm
  • 166
  • 1
  • 2
  • is it possible to make this work for filenames that include commas? special case i know, just wondering if it would be a simple addition or a lot of extra code. thanks – GeorgeCostanza Dec 19 '16 at 10:46
12

see this question

@echo OFF
set mydir="%~p1"
SET mydir=%mydir:\=;%

for /F "tokens=* delims=;" %%i IN (%mydir%) DO call :LAST_FOLDER %%i
goto :EOF

:LAST_FOLDER
if "%1"=="" (
    @echo %LAST%
    goto :EOF
)

set LAST=%1
SHIFT

goto :LAST_FOLDER
Community
  • 1
  • 1
asdfg
  • 2,541
  • 2
  • 26
  • 25
1

you can use a vbscript, eg save the below as getpath.vbs

Set objFS = CreateObject("Scripting.FileSystemObject")
Set objArgs = WScript.Arguments
strFile = objArgs(0)
WScript.Echo objFS.GetParentFolderName(strFile)

then on command line or in your batch, do this

C:\test>cscript //nologo getpath.vbs c:\test\pack\a.txt
c:\test\pack

If you want a batch method, you can look at for /?.

  %~fI        - expands %I to a fully qualified path name
  %~dI        - expands %I to a drive letter only
  %~pI        - expands %I to a path only
ghostdog74
  • 327,991
  • 56
  • 259
  • 343
1

Here's a way that does not use CALL and I believe is faster.Based on jeb's splitting function (might fail if the directory name contains !) :

@echo off

set "mydir=%~p1"
SET mydir=%mydir:~0,-1%

setlocal EnableDelayedExpansion
set LF=^


rem ** Two empty lines are required

for %%L in ("!LF!") DO (
    set "dir_name=!mydir:\=%%L!"
)
for /f "delims=" %%P in (""!dir_name!"") do set "dn=%%~P"
echo %dn%

exit /b 0 
npocmaka
  • 55,367
  • 18
  • 148
  • 187
1

I found this combination of approaches from the answers of djangofan and paranoid to be both, simple and perfectly sufficient, when looking up my script's parent directory:

set FULL_PATH=%~dp0
set FULL_PATH=%FULL_PATH:~1,-1%
for %%i in ("%FULL_PATH%") do set "PARENT_FOLDER=%%~ni"
echo %PARENT_FOLDER%

Since you want to work on user input instead, you have to do some minimal additional work, to handle legal variations like C:\foo\bar\a.txt vs. C:\foo\bar\a.txt or c:/foo/bar/a.txt. This might then work for you:

@setlocal
@echo off

call:GET_PARENT_FOLDER C:\foo\bar\a.txt
echo %PARENT_FOLDER%
call:GET_PARENT_FOLDER C:\foo\bar\\a.txt
echo %PARENT_FOLDER%
call:GET_PARENT_FOLDER c:/foo/bar/a.txt
echo %PARENT_FOLDER%

pause
goto:EOF

:GET_PARENT_FOLDER
:: Strip the filename, so we get something like this: 'C:\foor\bar\'
set "_FULL_PATH=%~dp1"

:: Strips all dangling '\' and '/' in a loop, so the last folder name becomes accessible
:_STRIP
if not "%_FULL_PATH:~-1%"=="\" if not "%_FULL_PATH:~-1%"=="/" goto:_STRIP_END
set "_FULL_PATH=%_FULL_PATH:~1,-1%"
goto:_STRIP
:_STRIP_END

:: We need the context of a for-loop for the special path operators to be available
for %%i in ("%_FULL_PATH%") do set "PARENT_FOLDER=%%~ni"

goto:EOF
DaDummy
  • 64
  • 3
1

The idea of DaDummy worked out in more practical reuseable functions. Also the first character of the _full_path is now included.

set map=D:\test1\test2\test3\test4.txt
call:get_parent_path "%map%"
echo full_path is %_full_path%
call:get_parent_path %_full_path%
echo full_path is %_full_path%
call:get_last_path %_full_path%
echo last_path is %_last_path%
goto :eof

:get_parent_path
set "_full_path=%~dp1"
:_strip
if not "%_full_path:~-1%"=="\" if not "%_full_path:~-1%"=="/" goto:_strip_end
set "_full_path=%_full_path:~0,-1%"
goto:_strip
:_strip_end
exit /b

:get_last_path
set "_last_path=%~nx1"
exit /b

::result:
::full_path is D:\test1\test2\test3
::full_path is D:\test1\test2
::last_path is test2
GerH
  • 11
  • 2
0

Here is another solution:

SET LAST=%CD%
SET PARENTNAME=NONE
cd /D C:\test\pack
FOR %%I in (%CD%) do SET PARENTNAME=%%~nI
cd /D %LAST%
ECHO %PARENTNAME%

%%~nI: '~n' extracts name from path stored in %%I variable
cd: '/D' parameter added to switch between disks also

paranoid
  • 119
  • 1
  • 2
0
call :set_dirname "%cd%"
echo %DIRNAME%


:set_dirname
set DIRNAME=%~n1
goto :eof
  • 2
    While this code may solve the question, [including an explanation](//meta.stackexchange.com/q/114762) of how and why this solves the problem would really help to improve the quality of your post, and probably result in more up-votes. Remember that you are answering the question for readers in the future, not just the person asking now. Please [edit] your answer to add explanations and give an indication of what limitations and assumptions apply. [From Review](/review/low-quality-posts/26186649) – double-beep May 21 '20 at 07:25
0

Here's one way to retrieve the name of the folder containing a file accessed by a CMD command. Using the OP's example of a file with path C:\test\pack\a.txt you would want your command to pull out that last folder name, "pack." (As dgnuff noted in a comment, the highest-scoring answer currently is an answer to a different question, and it won't help if you're in the OP's situation.)

The way I'm doing it is with nested FOR loops. Here's an example, as the command would appear in a batch file rather than entered directly on the command line:

FOR %%Z in ("*.txt") do (FOR %%I in ("%%~dpZ.") do (copy "%%~Z" "%%~dpZ%%~nxI.archive\%%~nxZ" ))

This example bach file command copies text files to a subfolder named after the folder with the files:

C:\test\pack\a.txt -> C:\test\pack\pack.archive\a.txt
C:\test\pick\b.txt -> C:\test\pick\pick.archive\b.txt
E:\A\B\C\D\foo.txt -> E:\A\B\C\D\D.archive\foo.txt

The outer FOR loop copies the files. But you need the inner FOR loop to build the destination path, since the destination subfolder name is based on the name of the source folder. The sequence "%%~dpZ." — with that dot after the Z — retrieves the name of the folder containing the current file, which can then be referenced via the parameter I (whereas Z is the reference to the file being copied). See the "Parameter Extensions" section on this page for review of the built-in variables used to build paths, as in "%%~dpZ%%~nxI.archive\%%~nxZ"

Joan Eliot
  • 267
  • 1
  • 8