Search code examples
for-loopbatch-filesymbols

Batch: for loop on files issue with symbol in name


Why does this for loop not work for files with "!" in the filename? And how can I make it recognize files with "!" or other possible symbols that may not work.

@Echo off
SETLOCAL EnableExtensions EnableDelayedExpansion
set my_dir=C:\Test
set my_ext=txt
cd /d !my_dir!
for %%F in ("*.!my_ext!") do (
    for /F "tokens=1,* delims=|" %%K in ('
        forfiles /M "%%~F" /C "cmd /C echo @path^|@ext"
    ') do (
        echo "%%~K": %%L
        set list=!list!%%~K;
    )
)

I get a returned message like this, with the ! missing from the output.

ERROR: Files of type "C:\Test\My file name has an explanation point here.txt" not found.

Solution

  • Here's an example of something which may work for you:

    @Echo Off
    SetLocal EnableExtensions DisableDelayedExpansion
    Set "my_dir=C:\Test"
    Set "my_ext=txt"
    CD /D "%my_dir%" 2> NUL || GoTo :EOF
    Set "list="
    For %%G In ("*.%my_ext%") Do (Echo "%%~fG"^|%%~xG
        If Not Defined list (Set "list=%%~fG") Else (
            For /F "Tokens=1*Delims==" %%H In ('Set list'
            ) Do Set "list=%%I;%%~fG"))
    SetLocal EnableDelayedExpansion
    Echo(!list!
    EndLocal
    Pause
    

    If you wanted each of your filepaths to be doublequoted, then a couple of small changes are all you need:

    @Echo Off
    SetLocal EnableExtensions DisableDelayedExpansion
    Set "my_dir=C:\Test"
    Set "my_ext=txt"
    CD /D "%my_dir%" 2> NUL || GoTo :EOF
    Set "list="
    For %%G In ("*.%my_ext%") Do (Echo "%%~fG"^|%%~xG
        If Not Defined list (Set "list="%%~fG"") Else (
            For /F "Tokens=1*Delims==" %%H In ('Set list'
            ) Do Set "list=%%I;"%%~fG""))
    SetLocal EnableDelayedExpansion
    Echo(!list!
    EndLocal
    Pause
    

    It is important to note, especially because you're using full paths for each of them, that there is a limit to the size of a user defined environment variable of 32767 characters. This means that depending upon the number of matching files in %my_dir%, you could exceed that maximum. In both examples, you can obviously remove the Echo "%%~fG"^|%%~xG part, if you didn't really require it.