Search code examples
batch-file

Writing filenames into a string using a loop


For a project, i must have a batch script responsible for FTP file uploading. For easier debuging / letting us know when a problem happens, if ftp upload is unsuccesful, i'd like to send a mail listing the files what were not uploaded. That is where i got stuck.

setlocal enabledelayedexpansion

REM winscp script call here

set exitCode=%ERRORLEVEL%
set file_list=
set file_count=0
set export_dir=D:\data\dir1\dir2

pause

echo Checking files in %export_dir%
dir %export_dir%
pause

REM issue here, with the loop probably
for %%i in (%export_dir%\*) do (
    set "filename=%%~nxi"
    echo Found file: !filename!
    set file_list=!file_list!!filename!<br>
    set /a file_count+=1
)

echo File List: !file_list!
echo File Count: %file_count%

pause

Something is wrong with the loop, and i cannot figure out what. Where and with what do I spoil it? Thx in advance!

I figured out that enabledelayedexpansion is a must, but still does not work. I've tried writing the directory content into a temporary file, did not work..


Solution

  • Substantially, your problem revolves around escaping redirectors.

    I'd also theorise that the file list you desire should be the list of files that were not copied, but your code seems to be directed at reporting those that were copied.

    Nonetheless, I'd suggest that you replace the problem section with ~

    set /a file_count=0
    :: remove variables starting file_list
    FOR  /F "delims==" %%e In ('set file_list 2^>Nul') DO SET "%%e="
    
    for %%i in (file1.txt file2.ext "file3 with space.wrx") do (
     echo Found file: %%~nxi
     set "file_list=!file_list!:%%~nxi"
     set /a file_count+=1
     SET "file_list[!file_count!]=%%~nxi"
    )
    SET "file_list=%file_list::=^<br^>%"
    ECHO File list %file_list:~6%^<br^>
    
    FOR %%e IN (1,1,%file_count%) DO ECHO !file_list[%%e]!^<br^>
    

    Which implements two different ways of approaching the problem. WHich you choose depends on what you actually want out, which you haven't specified.

    Note that I simply fed the loop with fixed filenames for testing. Naturally, you would change the for to supply the data you require to the loop.

    Method 1:

    If the required output is file1<br>file2<br>file3<br> then use only the lines not containing [. This builds file_list as you originally designed, but with a colon at the beginning & between the filenames. A colon since a colon can't appear in a filename. When the list has been built, replace each colon with ^<br^>, and show the result, all bar the first 6 characters and add a ^<br^> to the end.

    Method 2:

    If the required output is

    file1<br>
    file2<br>
    file3<br>
    

    then use the lines containing [. This assigns the filenames to file_list[n], one to each filename, then simply list them and append ^<br^>

    I'm assuming that the output is being delivered to a file for transmission, so use >>filename ECHO in place of ECHO to append the required output to the file.

    Naturally, beware of the variable-length limit and the influence of batch-sensitive characters like !%^& in filenames processed.

    Tip: Use set "var=value" for setting string values - this avoids problems caused by trailing spaces. Don't assign " or a terminal backslash or Space. Build pathnames from the elements - counterintuitively, it is likely to make the process easier. If the syntax set var="value" is used, then the quotes become part of the value assigned.