Below is a 'dostips' solution.
Quite obscure at the level of operations used, but very efficient !
*Example provided in the header should help to understand usage of this macro.
::=//////////////////////////////////////////////////////////////////////////
::= Makes a file name relative to a base path.
::= *param-1: file [in,out] - variable with file name to be converted, or file name itself for result in stdout
::= *param-2: base [in,opt*] - base path | *leave blank for current directory
::= *return: The resolved relative path is stored into *param-1
::=
::= SAMPLE*HOW-TO-USE:
::= a) Current path =D:\titi\toto\
::= b) DATAPATH_absolute =D:\titi\tata\tutu\log.txt
::= c) --relativize the data-path--
::=
::= c1) INIT the data:
::= $> set DATAPATH_relative=%DATAPATH_absolute%
::=
::= c2) CALL the sub-function:
::= $> call :MakeRelative DATAPATH_relative
::=
::= c3) (( After the call, result is set in %DATAPATH_relative% ))
::=
::= d) echo DATAPATH_relative =%DATAPATH_relative%
::= /---> "..\tata\tutu\log.txt"
::=
::= $source https://www.dostips.com
::= **web: https://www.dostips.com/?t=Function.MakeRelative
::= **web: https://www.dostips.com/DtCodeCmdLib.php#Function.MakeRelative
::=--------------------------------------------------------------------------
:MakeRelative
SETLOCAL ENABLEDELAYEDEXPANSION
set src=%~1
if defined %1 set src=!%~1!
set bas=%~2
if not defined bas set bas=%cd%
for /f "tokens=*" %%a in ("%src%") do set src=%%~fa
for /f "tokens=*" %%a in ("%bas%") do set bas=%%~fa
set mat=&rem variable to store matching part of the name
set upp=&rem variable to reference a parent
for /f "tokens=*" %%a in ('echo.%bas:\=^&echo.%') do (
set sub=!sub!%%a\
call set tmp=%%src:!sub!=%%
if "!tmp!" NEQ "!src!" (set mat=!sub!) ELSE (set upp=!upp!..\)
)
set src=%upp%!src:%mat%=!
( ENDLOCAL & REM RETURN VALUES
IF defined %1 (SET %~1=%src%) ELSE ECHO.%src%
)
EXIT /b
DosTips.com, :MakeRelative