Here is the batch code which should work.
@echo off
setlocal EnableDelayedExpansion
set "LOG_FILE=C:\program.log"
del "%LOG_FILE%" 2>nul
for /F "delims=" %%a in ('dir "C:\temp\*" 2^>nul') do call :LOGDEBUG "%%a"
endlocal
goto :EOF
:LOGDEBUG
set "StringToOutput=%~1"
echo DEBUG: !StringToOutput!
echo [%DATE% - %TIME%] DEBUG: !StringToOutput!>>"%LOG_FILE%"
goto :EOF
First delayed environment variable expansion is enabled and a copy of existing environment table is made. It is explained below why this is done.
Next the name of the log file with full path is assigned to an environment variable in local variable table. This path can be with or without 1 or more spaces in path. The log file is deleted in case of existing already from a previous run. This code can be removed if you want to append new lines to already existing file. But you should add in this case code to avoid that the log file permanently increases until no free storage space anymore.
The FOR command executes the command DIR and processes each line of the output of DIR written to stdout. Blank lines are skipped. The default delimiters are space, tab and newline characters. As wanted here are the entire lines of DIR, the default delimiter list is replaced by nothing which means only newline characters remain and loop variable %a
gets assigned always an entire non blank line.
The output of command DIR contains <
and >
which are interpreted as redirection operators if found by command processor within a line not quoted. Therefore the line for DIR output is passed quoted to subroutine LOGDEBUG
. Which characters must be usually quoted are listed on last help page printed into a command prompt window when executing cmd /?
in a command prompt window.
When the loop has finished, the local environment table is deleted which means LOG_FILE
and StringToOutput
are also removed, and previous environment is restored which usually means the delayed expansion is turned off again before batch execution exits with a jump to predefined label to end of file.
The subroutine LOGDEBUG
first assigns the passed string to an environment variable without surrounding quotes just needed because of special characters in line like <
and >
.
Next the line is written to console window without quotes using delayed expansion as otherwise <
and >
would be interpreted as redirecting operators and not literally.
The same line is written also to the log file with the difference of date and time inserted at beginning of line. You missed the percent sign after date
in your code. Again delayed expansion is used to get the line with the characters <
and >
written to file without being interpreted as redirection operators.
Important is also that there is no space before >>
as otherwise each line in log file would have a trailing space. 2>&1
is useless here as command echo does not write something to stderr.
The subroutine is exited with a jump to end of file resulting in command FOR processes next line.
For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.
call /?
del /?
dir /?
for /?
goto /?
set /?
It would be of course possible to do all the output directly in body of command FOR without using a subroutine.
@echo off
setlocal EnableDelayedExpansion
set "LOG_FILE=C:\program.log"
del "%LOG_FILE%" 2>nul
for /F "delims=" %%a in ('dir "C:\temp\*" 2^>nul') do (
echo DEBUG: %%a
echo [!DATE! - !TIME!] DEBUG: %%a>>"%LOG_FILE%"
)
endlocal
Delayed variable expansion is nevertheless required here as otherwise %DATE%
and %TIME%
would be expanded by command processor like %LOG_FILE%
already on parsing entire block defined by (
and )
before command FOR is executed at all which would result in same date and time written for all lines to the log file.