One approach is to nest a for %I loop within the forfiles and use the %~I expansion -- use this code in a Command Prompt window:
forfiles /P "C:\root" /M "*.txt" /C "cmd /Q /C for %I in (@relpath) do echo %~I"
To use that code within a batch file you must double the %-signs:
forfiles /P "C:\root" /M "*.txt" /C "cmd /Q /C for %%I in (@relpath) do echo %%~I"
The returned list of files will be (relying on the sample files from the original question):
.\file1.txt
.\file2.txt
Another variant is to nest another forfiles in the body of the initial one, because forfiles removes (non-escaped) double-quotes within given strings like the command line after /C:
forfiles /P "C:\root" /M "*.txt" /C "cmd /C forfiles /P @path\.. /M @file /C \"cmd /C echo @relpath\""
Or alternatively (the doubled inner forfiles is intentional, this works around a bug -- see this post):
forfiles /P "C:\root" /M "*.txt" /C "forfiles forfiles /P @path\.. /M @file /C \"cmd /C echo @relpath\""
The inner forfiles will enumerate exactly one item, which is the one passed over by the outer loop. Since @relpath is already expanded when the inner loop is executed, the quotes are removed as they are not escaped.
So the returned list of files looks like (again taking the sample files from the original question):
.\file1.txt
.\file2.txt
The additional line-break between the lines is generated by forfiles. You can avoid that using redirection (dismiss forfiles output, but display only the echo output in the console window):
> nul forfiles /P "C:\root" /M "*.txt" /C "cmd /C forfiles /P @path\.. /M @file /C 0x22cmd /C > con echo @relpath0x22"