If you want filenames with paths then:
@(For /F Delims^= %%G In ('Dir /B/S/AD/ON')Do @Set "}=?"&For /F "EOL=? Delims=" %%H In ('Dir "%%G" /B/A-D/ON 2^>NUL')Do @If Defined } Echo %%G\%%H&Set "}=")>"filelist.txt"
If you wanted the filenames only then similarly:
@(For /F Delims^= %%G In ('Dir /B/S/AD/ON')Do @Set "}=?"&For /F "EOL=? Delims=" %%H In ('Dir "%%G" /B/A-D/ON 2^>NUL')Do @If Defined } Echo %%H&Set "}=")>"filelist.txt
However, please be aware that the above method will still enumerate each directory after it has output the first file in each, so if there are many files in one or more of those it may not be the most efficient of methods.
In that case, it may be more efficient to Call
a label instead:
@(For /F Delims^= %%G In ('Dir /B/S/AD/ON')Do @Call:Sub "%%G")>"filelist.txt"
@GoTo :EOF
:Sub
@For /F "EOL=? Delims=" %%G In ('Dir %1 /B/A-D/ON 2^>NUL')Do @Echo "%~1\%%G"&Exit /B
@Echo ;"%~1"&Exit /B
The above example is designed to also print the directories containing no child files, prefixed with a semicolon. If you don't want those, then just remove Echo ;"%~1"&
from the last line. Also if you don't want the full paths, just remove %~1\
from the penultimate line.
If you wanted to output to the file on each iteration, instead of writing all of the output at the end only, (according to your comment below), then the following is an adaption of the first example, to show you how to do that:
@For /F Delims^= %%G In ('Dir /B/S/AD/ON')Do @Set "}=?"&For /F "EOL=? Delims=" %%H In ('Dir "%%G" /B/A-D/ON 2^>NUL')Do @If Defined } Echo "%%G\%%H">>"filelist.txt"&Set "}="