batch-file

How to get the relative path for each file in a directory tree based on specified folder path?


I want to loop recursively through a directory and get the file names with full file path and additionally with path relative to the base folder path. For example, a file located in D:\foo\bar\a\b\file.txt has the relative path bar\a\b\.

I'm using this code right now which does not work as expected:

FOR /R D:\Download\758_DATA\ %%F IN (*) DO (
    SET B = %%~pF
    Set B=%B:~-6%  ::take substring of the path
    ECHO.%B%
    ECHO %%F 
    ECHO.
)

Solution

  • I'm not sure what you want to accomplish, but at least this will give you a good starting point:

    @echo off & setlocal enabledelayedexpansion
    
    set rootdir=D:\download
    
    for /R %rootdir% %%F in (*) do (
        set "B=%%~pF"
        set "B=!B:~10!"
        echo Full   : %%F
        echo Partial: !B!
        echo(
    )
    
    endlocal
    

    Since you're modifying a variable within a loop, you need to tell the command interpreter that you want to allow variables to be "expanded with delay". This is what the setlocal enabledelayedexpansion is for. Then you can use ! as a variable delimiter instead of %, and variables written as such will be expanded at runtime. This is necessary because the for loop will be called like it is one single call. (You can see this when you leave out the echo off.)

    Edit: Revised example which includes automatic cut off:

    @echo off
    setlocal enableextensions enabledelayedexpansion
    
    set "rootdir=%~f1"
    if not defined rootdir set "rootdir=%CD%"
    set "rootdir=%rootdir:/=\%"
    if "%rootdir:~-1%" == "\" set "rootdir=%rootdir:~0,-1%"
    set "foo=%rootdir%"
    set cut=
    :loop
    if defined foo (
        set /A cut+=1
        set "foo=!foo:~1!"
        goto :loop
    )
    echo Root dir: %rootdir%
    echo strlen  : %cut%
    
    rem also remove leading /
    set /A cut+=1
    
    for /R "%rootdir%" %%F in (*) do (
        set "B=%%~fF"
        rem take substring of the path
        set "B=!B:~%cut%!"
        echo Full    : %%F
        echo Partial : !B!
        echo(
    )
    endlocal