这是应该工作的批处理代码。
@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
启用首次延迟的环境变量扩展并创建现有环境表的副本。下面解释为什么这样做。
接下来将具有完整路径的日志文件的名称分配给局部变量表中的环境变量。此路径可以带有或不带有1个或更多空间。如果以前的运行已经存在,日志文件将被删除。如果您想将新行添加到已存在的文件中,则可以删除此代码。但在这种情况下,应该添加代码以避免日志文件永久增加,直到不再有空闲存储空间。
的FOR命令执行命令DIR并处理DIR的输出写入到标准输出的每一行。空白行被跳过。默认分隔符是空格,制表符和换行符。正如这里所要求的是DIR的全部行,默认分隔符列表被替换为空,这意味着只有换行符保留,并且循环变量%a
总是被分配一个完整的非空行。
命令的输出DIR包含<
和>
如果没有引用的线内发现由命令处理器,其被解释为redirection operators。因此,DIR输出的行通过引用子程序LOGDEBUG
。在命令提示符窗口中执行cmd /?
时,必须通常引用哪些字符列在打印到命令提示符窗口的最后一个帮助页面上。
当循环结束时,本地环境表被删除,这意味着LOG_FILE
和StringToOutput
也被删除,并且以前的环境被恢复,这通常意味着在批量执行退出并跳转到预定义标签之前,延迟扩展会再次关闭到文件结尾。
该子程序LOGDEBUG
首先将传递的字符串分配给一个环境变量,不需要使用周围的引号,因为行中的特殊字符如<
和>
。
接下来将该行写入控制台窗口,而不使用延迟扩展引号,否则<
和>
将被解释为重定向运算符,而不是字面意思。
将同一行写入日志文件,并在行首插入日期和时间的差异。您错过代码中的date
之后的百分号。再次延迟扩展用于将字符<
和>
写入文件而不被解释为重定向操作符。
重要的是,在>>
之前没有空格,否则日志文件中的每行都会有尾随空格。 2>&1
在这里没用,作为命令echo没有写点东西给stderr。
子程序退出时跳转到文件结尾,导致命令FOR处理下一行。
为了解所使用的命令及其工作方式,请打开命令提示符窗口,在其中执行以下命令,并仔细阅读为每个命令显示的所有帮助页面。
call /?
del /?
dir /?
for /?
goto /?
set /?
这将是当然可以做所有的输出可怕在命令主体FOR中可以不使用子程序。
@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
延迟变量扩展然而这里需要另有%DATE%
和%TIME%
将由命令处理器等扩大已经在解析FOR命令之前通过(
和)
定义整个块在所有这将导致执行将相同的日期和时间写入日志文件的所有行。
检查此http://stackoverflow.com/a/10719322/388389 – npocmaka
如何定义'%LOG_FILE%'变量?并尝试'echo CALL:LOGDEBUG“%% a”'而不是'CALL:LOGDEBUG“%% a”'来查看例如'CALL:LOGDEBUG“驱动器C中的卷是SysDisk”'(: – JosefZ
嗨@npocmaka,我希望在打印前格式化日志文件和控制台输出,我想我不能直接使用tee.bat,对吗? – Elliott