69

How do I split the filename out of a full path in batch scripting?

iTayb
  • 12,373
  • 24
  • 81
  • 135
  • 2
    possible duplicate of [Batch Extract path and filename from a variable](http://stackoverflow.com/questions/15567809/batch-extract-path-and-filename-from-a-variable) – Gab Mar 31 '15 at 08:33

6 Answers6

94
@echo off
Set filename=C:\Documents and Settings\All Users\Desktop\Dostips.cmd
For %%A in ("%filename%") do (
    Set Folder=%%~dpA
    Set Name=%%~nxA
)
echo.Folder is: %Folder%
echo.Name is: %Name%

But I can't take credit for this; Google found this at http://www.dostips.com/forum/viewtopic.php?f=3&t=409

Pete Stensønes
  • 5,595
  • 2
  • 39
  • 62
  • 1
    Thanks! This worked for me too. I'm reading in a list of folders from a file and formatting them. I used this: "for /F "tokens=1 delims=" %%A in (list_of_files.txt) do (" – Mike Q Jun 12 '13 at 16:43
  • 1
    Might be nice to show how to get just the file name. (Without the extension.) – Vaccano Oct 17 '13 at 20:43
  • 3
    %~nI - expands %I to a file name only <- taken direct from teh DOS "for -help" output. – Pete Stensønes Oct 18 '13 at 09:03
  • 6
    To help clarify, d means include the drive, p include the path, n include the file name, x include the extension. – makhdumi Nov 20 '13 at 22:17
35

Parse a filename from the fully qualified path name (e.g., c:\temp\my.bat) to any component (e.g., File.ext).

Single line of code:

For %%A in ("C:\Folder1\Folder2\File.ext") do (echo %%~fA)

You can change out "C:\Folder1\Folder2\File.ext" for any full path and change "%%~fA" for any of the other options you will find by running "for /?" at the command prompt.

Elaborated Code

set "filename=C:\Folder1\Folder2\File.ext"
For %%A in ("%filename%") do (
    echo full path: %%~fA
    echo drive: %%~dA
    echo path: %%~pA
    echo file name only: %%~nA
    echo extension only: %%~xA
    echo expanded path with short names: %%~sA
    echo attributes: %%~aA
    echo date and time: %%~tA
    echo size: %%~zA
    echo drive + path: %%~dpA
    echo name.ext: %%~nxA
    echo full path + short name: %%~fsA)

Standalone Batch Script
Save as C:\cmd\ParseFn.cmd.

Add C:\cmd to your PATH environment variable and use it to store all of you reusable batch scripts.

@echo off
@echo ::___________________________________________________________________::
@echo ::                                                                   ::
@echo ::                              ParseFn                              ::
@echo ::                                                                   ::
@echo ::                           Chris Advena                            ::
@echo ::___________________________________________________________________::
@echo.

::
:: Process arguements
::
if "%~1%"=="/?" goto help
if "%~1%"=="" goto help
if "%~2%"=="/?" goto help
if "%~2%"=="" (
    echo !!! Error: ParseFn requires two inputs. !!!
    goto help)

set in=%~1%
set out=%~2%
:: echo "%in:~3,1%"   "%in:~0,1%"
if "%in:~3,1%"=="" (
    if "%in:~0,1%"=="/" (
    set in=%~2%
    set out=%~1%)
)

::
:: Parse filename
::
set "ret="
For %%A in ("%in%") do (
    if "%out%"=="/f" (set ret=%%~fA)
    if "%out%"=="/d" (set ret=%%~dA)
    if "%out%"=="/p" (set ret=%%~pA)
    if "%out%"=="/n" (set ret=%%~nA)
    if "%out%"=="/x" (set ret=%%~xA)
    if "%out%"=="/s" (set ret=%%~sA)
    if "%out%"=="/a" (set ret=%%~aA)
    if "%out%"=="/t" (set ret=%%~tA)
    if "%out%"=="/z" (set ret=%%~zA)
    if "%out%"=="/dp" (set ret=%%~dpA)
    if "%out%"=="/nx" (set ret=%%~nxA)
    if "%out%"=="/fs" (set ret=%%~fsA)
)
echo ParseFn result: %ret%
echo.

goto end
:help
@echo off
:: @echo ::___________________________________________________________________::
:: @echo ::                                                                   ::
:: @echo ::                           ParseFn Help                            ::
:: @echo ::                                                                   ::
:: @echo ::                           Chris Advena                            ::
:: @echo ::___________________________________________________________________::
@echo.
@echo ParseFn parses a fully qualified path name (e.g., c:\temp\my.bat)
@echo into the requested component, such as drive, path, filename, 
@echo extenstion, etc.
@echo.
@echo Syntax: /switch filename
@echo where,
@echo   filename is a fully qualified path name including drive, 
@echo   folder(s), file name, and extension
@echo.
@echo   Select only one switch:
@echo       /f - fully qualified path name
@echo       /d - drive letter only
@echo       /p - path only
@echo       /n - file name only
@echo       /x - extension only
@echo       /s - expanded path contains short names only
@echo       /a - attributes of file
@echo       /t - date/time of file
@echo       /z - size of file
@echo      /dp - drive + path
@echo      /nx - file name + extension
@echo      /fs - full path + short name
@echo.

:end
:: @echo ::___________________________________________________________________::
:: @echo ::                                                                   ::
:: @echo ::                         ParseFn finished                          ::
:: @echo ::___________________________________________________________________::
:: @echo.
cadvena
  • 1,063
  • 9
  • 17
  • 'Elaborated code' potentially has an error; d is not directory entry? Or different effects when in a batch file? As the 'standalone batch script' indicates? – user3082 Sep 08 '19 at 11:22
7
@echo off
Set filename="C:\Documents and Settings\All Users\Desktop\Dostips.cmd"
call :expand %filename%
:expand
set filename=%~nx1
echo The name of the file is %filename%
set folder=%~dp1
echo It's path is %folder%
C_urious' '
  • 101
  • 2
  • 5
  • When I run this, it outputs the lines twice. I'm not sure how to fix this. This is the output: `The name of the file is Dostips.cmd It's path is C:\Documents and Settings\All Users\Desktop\ The name of the file is It's path is` – Ste Jan 19 '20 at 23:35
  • **This** only happens when the path doesn't exist. Any way around that without an if statement? But this is a neat solution, so thank you. – Ste Jan 20 '20 at 00:24
  • No that wasn't it either. If I add `echo anther line` to the bottom of that code, it behaves the same. – Ste Jan 20 '20 at 00:33
1

Continuing from Pete's example above, to do it directly in the cmd window, use a single %, eg:

cd c:\test\folder A
for %X in (*)do echo %~nxX

(Note that special files like desktop.ini will not show up.)

It's also possible to redirect the output to a file using >>:

cd c:\test\folder A
for %X in (*)do echo %~nxX>>c:\test\output.txt

For a real example, assuming you want to robocopy all files from folder-A to folder-B (non-recursively):

cd c:\test\folder A
for %X in (*)do robocopy . "c:\test\folder B" "%~nxX" /dcopy:dat /copyall /v>>c:\test\output.txt

and for all folders (recursively):

cd c:\test\folder A
for /d %X in (*)do robocopy "%X" "C:\test\folder B\%X" /e /copyall /dcopy:dat /v>>c:\test\output2.txt
Pacerier
  • 86,231
  • 106
  • 366
  • 634
  • While using this I just discovered if you use these techniques with robocopy you also need to remember to remove the last backslash in the source directory. It would be useful if there was an example which uses `%~dpX` as source. – AnnanFay Mar 27 '17 at 14:30
0

Just want to share my 2c after I need this for my batch script. Using for is not helping at all since I want a literal dir and filemask.

ie. given the c:\dir1\subdir\*.asm, I need both literal c:\dir1\subdir and *.asm for further processing

:parsepathname pathname dirname filename
  @echo OFF
  if "%~3"=="" exit /b -1 ERROR!
  setlocal enableDelayedExpansion
  set "dirname="
  set "filename=%~1"
  set "check=%filename:\=%"
  if "%check%"=="%filename%" goto pfn_Love1Done
  set "ctr=0" & set "pathname=%~1" & set "filename="
  :pfn_Love1
    if ctr LSS -260 exit /b -2 ERROR!
    set /a "ctr-=1"
    set "ch=!pathname:~%ctr%,1!" 
    if not "%ch%"=="\" goto pfn_Love1
    set "dirname=!pathname:~0,%ctr%!"
    set /a "ctr+=1"
    set "filename=!pathname:~%ctr%!"
  :pfn_Love1Done
  rem echo DEBUG: pathname="%pathname%" dirname="%dirname%" filename="%filename%"
  endlocal & set "%~2=%dirname%" & set "%~3=%filename%"
exit /b

call withcall %pathname% dirname filename, dirnameandpathname

  • `@(set "%~2=%~dp0" & set "%~3=%~nx1")` (yes, as the one and only line) - only difference is the backslash at the end of the folder path. – Stephan Mar 03 '23 at 21:54
  • No. As I said, I dont want the wildcard to be interpreted as filename. I need the literal wildcard itself, for example to be processed further by `for /r dir in (wildcard)`. All solutions presented here, including yours, will translate `%~nxf` as the last filename found. NOT the wildcard itself. that's a HUGE different. Maybe most users don't need my solution, I just presented it for those 1% users who need it and do not know how. – user6801759 Mar 04 '23 at 07:20
  • Of course, mine is not the only solution for that requirement. You can, for example substitute the path with empty string `set filename="%pathname:%~dpf/=%"` works most of the time, still have to be checked if pathname containing drive letter or whether if it has any dir portion at all. – user6801759 Mar 04 '23 at 07:44
  • Sorry, misinterpreted your problem (my line works fine *only* if no file matches the mask) – Stephan Mar 04 '23 at 08:32
0

I don't know that much about batch files but couldn't you have a pre-made batch file copied from the home directory to the path you have that would return a list of the names of the files then use that name?

Here is a link I think might be helpful in making the pre-made batch file.

http://www.ericphelps.com/batch/lists/filelist.htm

Spencer May
  • 4,266
  • 9
  • 28
  • 48