Batch files: list of all files in a directory with relative paths

Regarding Windows batch files: is there a way to list all files (or all of a specific type) in a specific directory and its subdirectories, including paths relative to the current (or search) directory in the list?

For example, if I want all txt files in the current directory and subdirectories with their full paths, I can do

for /r . %%g in (*.txt) do echo %%g >> C:\temp\test.txt 

or

 dir *.txt /b /s >> C:\temp\test.txt 

and i will get something like

 C:\test\Doc1.txt C:\test\subdir\Doc2.txt C:\test\subdir\Doc3.txt 

If i do

 for /r . %%g in (*.txt) do echo %%~nxg >> C:\temp\test.txt 

I will get something like

 Doc1.txt Doc2.txt Doc3.txt 

But I really want:

 Doc1.txt subdir\Doc2.txt subdir\Doc3.txt 

Is it possible?

If my post is too confusing: I basically want to " recursively list files in the Linux CLI with an outline relative to the current directory ", for Windows only.

+55
windows cmd batch-file
Dec 05 '11 at 12:40
source share
5 answers

You can simply get the character length of the current directory and remove them from your absolute list

 setlocal EnableDelayedExpansion for /L %%n in (1 1 500) do if "!__cd__:~%%n,1!" neq "" set /a "len=%%n+1" setlocal DisableDelayedExpansion for /r . %%g in (*.log) do ( set "absPath=%%g" setlocal EnableDelayedExpansion set "relPath=!absPath:~%len%!" echo(!relPath! endlocal ) 
+22
Dec 05 '11 at 2:47 a.m.
source share

The easiest (but not the fastest) way to iterate over a directory tree and a list of relative file paths is to use FORFILES .

 forfiles /s /m *.txt /c "cmd /c echo @relpath" 

Relative paths will be indicated with the leading .\ , As in

 ".\Doc1.txt" ".\subdir\Doc2.txt" ".\subdir\Doc3.txt" 


To remove quotes:

 for /f %%A in ('forfiles /s /m *.txt /c "cmd /c echo @relpath"') do echo %%~A 


To remove quotes and leading .\ :

 setlocal disableDelayedExpansion for /f "delims=" %%A in ('forfiles /s /m *.txt /c "cmd /c echo @relpath"') do ( set "file=%%~A" setlocal enableDelayedExpansion echo !file:~2! endlocal ) 

or without deferred extension

 for /f "tokens=1* delims=\" %%A in ( 'forfiles /s /m *.txt /c "cmd /c echo @relpath"' ) do for %%F in (^"%%B) do echo %%~F 
+31
Aug 31 2018-12-12T00:
source share

This answer will not work correctly with root paths containing equal signs ( = ). (Thanks to @dbenham for pointing this out.)




EDITED: Fixed issue with paths containing ! again noticed by @dbenham (thanks!).

Alternatively, you can use a different approach to calculate the length and extract substrings:

  • save the root path;

  • clear root path from file paths.

Here is my attempt (which worked for me):

 @ECHO OFF SETLOCAL DisableDelayedExpansion SET "r=%__CD__%" FOR /R . %%F IN (*) DO ( SET "p=%%F" SETLOCAL EnableDelayedExpansion ECHO(!p:%r%=! ENDLOCAL ) 

The variable r is assigned by the current directory. If the current directory is not the root directory of the disk drive, it does not end with \ , which we correct by adding a character. (Not anymore, since the script now reads the __CD__ variable, the value of which always ends with \ (thanks @jeb!) instead of CD .)

In the loop, we save the current path to the variable. Then we output the variable by removing the root path along the path.

+9
Dec 05 '11 at 19:16
source share

Of course, you can write a recursive algorithm in Batch that gives you precise control over what you do in each nested subdirectory:

 @echo off set mypath= call :treeProcess goto :eof :treeProcess setlocal for %%f in (*.txt) do echo %mypath%%%f for /D %%d in (*) do ( set mypath=%mypath%%%d\ cd %%d call :treeProcess cd .. ) endlocal exit /b 
+4
Dec 6 '11 at 10:32
source share
 @echo on>out.txt @echo off setlocal enabledelayedexpansion set "parentfolder=%CD%" for /r . %%g in (*.*) do ( set "var=%%g" set var=!var:%parentfolder%=! echo !var! >> out.txt ) 
+2
Oct 26 '12 at 5:45
source share



All Articles