【问题标题】:How to add time stamp to log lines in log file from batch file output?如何从批处理文件输出向日志文件中的日志行添加时间戳?
【发布时间】:2018-08-31 05:56:24
【问题描述】:

我想为批处理输出的日志行添加时间戳。

这是我的批处理文件:

@Echo off
SET LOGFILE=MyLogFile.log
call :Logit >> %LOGFILE% 
exit /b 0

:Logit
set "affix=%date%_%time%"
set "affix=%affix::=%"
set "affix=%affix:/=%"
xcopy "I:\DF\AB\Data.xlsx" "D:\TL\BACKUP\Data_%affix%.xlsx"*

日志文件的输出:

I:\DF\AB\Data.xlsx
1 File(s) copied

我希望输出日志文件如下所示:

I:\DF\AB\Data.xlsx
20180831_124500 : 1 File(s) copied

如何做到这一点?

更多信息:

  1. 在没有提示的情况下复制文件需要目标参数字符串末尾的星号。如果* 不会在目标文件名的末尾使用,则会提示询问目标是文件还是目录。
  2. 使用xcopy 是因为将文件从网络驱动器复制到本地驱动器。

运行批处理文件后的输出结果如下:

I:\DF\AB\Data.xlsx
08312018_163959.07 :I:\DF\AB\Data.xlsx
1 File(s) copied

可能是下面这样吗?

I:\DF\AB\Data.xlsx
08312018_163959.07  1 File(s) copied 

所以区域相关的日期格式是MM/DD/YYY,时间格式是HH:mm:ss.ms

【问题讨论】:

  • 就在最后一行的下方,把这行echo %affix% 设置为你想要复制文件的所有内容,但只是在调用标签时,它会将修改的时间和日期回显到文件复制后的日志文件..

标签: batch-file timestamp logfile


【解决方案1】:

您只有XCopying 一个文件,因此您知道成功时的最后一行输出将是与语言相关的字符串1 File(s) copied
因为您已经将脚本限制为使用语言环境依赖%DATE%%TIME%,我假设这个任务的语言依赖是好的。

因此,这是一个看起来很荒谬的示例脚本:

@Echo Off
Set "srcfile=I:\DF\AB\Data.xlsx"
Set "destdir=D:\TL\BACKUP"
Set "logfile=MyLogFile.log"

For %%A In ("%srcfile%") Do Set "dstname=%%~nA" & Set "destext=%%~xA"

For /F "Tokens=1-2 Delims=|" %%A In ('
    Echo F^|XCopy "%srcfile%" "|%DATE:/=%_%TIME::=%|" /L 2^>Nul ^&^
    Echo F^|Xcopy "%srcfile%" "%destdir%\%dstname%_%DATE:/=%_%TIME::=%%destext%" /Y ^>Nul 2^>^&1
') Do (If Not "%%B"=="" Set "_=%%B"
    If Defined _ If /I "%%A"=="%srcfile%" ((
            Echo %%A&Call Echo %%_%%  1 File(s^) copied)>"%logfile%"))

除了行 2-4 上的变量值外,您不应更改任何内容。
但是,您应该使用现有日志文件,您不妨将最后一行的 > 更改为 >>

【讨论】:

    【解决方案2】:

    您可以使用echo| set /p=%affix% 在回显时消除换行符:

    @Echo off
    SET LOGFILE=MyLogFile.log
    call :Logit >> %LOGFILE% 
    exit /b 0
    :Logit
    set "affix=%date%_%time%"
    set "affix=%affix::=%"
    set "affix=%affix:/=%"
    echo|set /p=%affix% :
    xcopy "I:\DF\AB\Data.xlsx" "D:\TL\BACKUP\Data_%affix%.xlsx"*
    

    结果:

    I:\DF\AB\Data.xlsx
    2018-08-31_124900 :        1 file(s) copied.
    

    【讨论】:

    • @v1787v。这是我能做的最好的,我删除了文件 echo 因为它是一个测试,但是你的结果不能和这个不同,你不能默认分割命令的输出,他们唯一可能的方法是创建一个 for 循环,将命令传递给 nul,然后使用输出并将其拆分为变量并回显到文件。但这似乎真的没有必要。
    【解决方案3】:

    powershell -command "(New-TimeSpan -Start (Get-Date "01/01/1970") -End (Get- Date)).TotalSeconds">LOG.TXT

    虽然这不是您建议的格式,但这种格式称为epoch time
    这种格式的好处是它始终是一个浮点值。

    LOG.TXT 将是日志的名称,请确保您位于正确的目录中。

    【讨论】:

    • 非常感谢本杰明2002
    【解决方案4】:

    我建议以下代码在日志文件中产生最初想要的输出:

    @echo off
    setlocal EnableExtensions DisableDelayedExpansion
    set "LOGFILE=MyLogFile.log"
    del "%LOGFILE%" 2>nul
    call :Logit >>"%LOGFILE%"
    endlocal
    exit /B 0
    
    :Logit
    set "FileDate=%DATE:~-4%%DATE:~-10,2%%DATE:~-7,2%_%TIME:~0,2%%TIME:~3,2%%TIME:~6,2%"
    for /F "tokens=1* delims=:" %%I in ('%SystemRoot%\System32\xcopy.exe "I:\DF\AB\Data.xlsx" "D:\TL\BACKUP\Data_%FileDate%.xlsx*" /C /V /Y 2^>nul') do (
        if not "%%J" == "" (
            echo %%I:%%J
        ) else (
            echo %FileDate% : %%I
        )
    )
    goto :EOF
    

    通过使用动态环境变量DATETIME 的字符串替换将依赖于区域的日期和时间重新格式化为yyyyMMdd_HHmmss,例如通过问题的答案详细解释:What does %date:~-4,4%%date:~-10,2%%date:~-7,2%_%time:~0,2%%time:~3,2% mean?速度较慢但与地区无关的解决方案,要以特定格式获取日期/时间,请参阅以下答案:Why does %date% produce a different result in batch file executed as scheduled task?

    yyyyMMdd_HHmmss 格式的当前日期和时间分配给环境变量FileDate 在下一行使用了两次,一次在目标文件的名称中,一次在重新格式化的命令输出的最后一行的输出中 XCOPY

    这里使用的XCOPY命令行例如:

    C:\Windows\System32\xcopy.exe "I:\DF\AB\Data.xlsx" "D:\TL\BACKUP\Data_20180831_163959.xlsx*" /C /R /V /Y 2>nul
    

    此命令行由 FOR 在由 FOR 启动的单独命令进程中执行,cmd.exe /C 在后台运行。 FOR 在处理捕获的行之前捕获为处理此命令进程的 STDOUT 而编写的所有行。

    XCOPY 输出以处理 STDOUT 复制文件的名称以及完整路径,最后一行是摘要信息。写入文件复制错误以处理 STDERR,通过将它们重定向到设备 NUL 来抑制这些错误。

    另请阅读有关Using command redirection operators 的Microsoft 文章,了解2>nul 的解释。重定向运算符 > 必须在 FOR 命令行上使用插入字符 ^ 转义,以便在 Windows 命令解释器在执行命令 FOR 之前处理此命令行时解释为文字字符> 在后台启动的单独命令进程中执行嵌入的xcopy 命令行。

    目标文件名末尾的星号* 应该在第二个参数字符串的双引号内,而不是在外,否则cmd.exexcopy.exe 必须更正这个错误的语法。

    请注意,目标文件名末尾带有* 的技巧在这里偶然起作用,因为源文件和目标文件具有相同的文件扩展名,并且源文件名总是比目标文件名短。否则命令将失败或目标文件得到一个不需要的名称,即目标文件名 + 目标文件名 n 个字符后的源文件名字符的串联。

    通常有更好的方法可以避免在使用新文件名复制单个文件时 XCOPY 请求的提示停止。回答提示的字母可以首先输出到 STDOUT 重定向到处理 XCOPY 命令的 STDIN,如在batch file asks for file or folder 的回答中证明的语言无关.

    XCOPY 的捕获输出由 FOR 逐行处理,跳过空行和以分号 ; 开头的行作为默认行尾字符选项eol= 未在此处使用。

    这里的目标是在后台命令进程中也输出由 XCOPY 输出的具有完全限定文件的所有行,但在此命令进程中输出带有不同摘要信息的最后一行所需格式的日期/时间、一个空格、一个冒号和一个空格。

    因此,空格/制表符上的默认行拆分行为仅将第一个子字符串(标记)分配给指定的循环变量I,此处由选项tokens=1* delims=: 修改。 FOR 现在在冒号上分割一行。

    只有完全限定文件名以驱动器号和冒号开头的行才包含冒号。在这样的行中,驱动器号被分配给指定的循环变量I,由tokens=1 指定。第一个冒号之后的文件名行的其余部分被分配,没有根据ASCII table 将循环变量J 分配给下一个循环变量,这里是驱动器号之后冒号之后的所有内容。

    摘要信息行不包含冒号。为此,FOR 将整个摘要信息分配给循环变量I,而J 包含一个空字符串。

    循环变量J 在文件名以驱动器号和冒号开头的行上从不为空。此处使用此事实来确定是否应按原样输出 XCOPY 中的行,在驱动器号和文件路径 + 文件名 + 文件扩展名之间插入已删除的冒号,或输出带有日期/时间的摘要信息一开始。

    请注意,此方法仅适用于从带有驱动器号的驱动器复制文件。对于具有UNC 路径的源文件,需要使用不同的方法。

    事实上,使用命令 COPY 而不是 XCOPY 可以更轻松地复制单个文件,即使从/到网络驱​​动器或在指定源/目标文件名时带有 UNC 路径。 COPY 还有/V/Y 甚至/Z 选项,例如XCOPYCOPY 不会像 XCOPY 那样创建目标目录结构,但这可以通过之前的命令 MD 来完成。 COPY 不能像 XCOPY 在使用选项 /R 时那样覆盖只读文件,但这种 COPY 的限制很可能在这里不相关。 COPY 不会复制设置了隐藏属性的文件。但是,通常最好使用命令 COPY 而不是 XCOPY 来复制单个文件。

    所以这里是使用命令 COPY 的另一种解决方案,它比 XCOPY 解决方案更快,因为没有理由在单独的命令进程中执行文件复制,捕获任何行,将它们拆分并再次连接或修改输出。

    @echo off
    setlocal EnableExtensions DisableDelayedExpansion
    set "LOGFILE=MyLogFile.log"
    md "D:\TL\BACKUP" 2>nul
    del "%LOGFILE%" 2>nul
    call :Logit >>"%LOGFILE%"
    endlocal
    exit /B 0
    
    :Logit
    set "FileDate=%DATE:~-4%%DATE:~-10,2%%DATE:~-7,2%_%TIME:~0,2%%TIME:~3,2%%TIME:~6,2%"
    echo I:\DF\AB\Data.xlsx
    copy /B /V /Y "I:\DF\AB\Data.xlsx" "D:\TL\BACKUP\Data_%FileDate%.xlsx" >nul 2>nul && echo %FileDate% : 1 File(s) copied|| echo %FileDate% : 0 File(s) copied
    goto :EOF
    

    此解决方案还有一个优点,即成功或错误的行输出可以完全自定义。 COPY 以大于 0 的值退出源文件不可用或目标文件/目录当前或永久写保护等错误。

    成功或错误时单个复制文件的更好输出示例(仅限子例程):

    :Logit
    set "FileDate=%DATE:~-4%%DATE:~-10,2%%DATE:~-7,2%_%TIME:~0,2%%TIME:~3,2%%TIME:~6,2%"
    copy /B /V /Y "I:\DF\AB\Data.xlsx" "D:\TL\BACKUP\Data_%FileDate%.xlsx" >nul 2>nul
    if not errorlevel 1 (
        echo %FileDate% : Copied successfully I:\DF\AB\Data.xlsx
    ) else (
        echo %FileDate% : Failed to copy file I:\DF\AB\Data.xlsx
    )
    goto :EOF
    

    当然也可以使用命令行

    set "FileDate=%DATE:/=%_%TIME::=%"
    

    如果现在真的需要,在批处理文件中以MMddyyyy_HHmmss.ms 格式获取日期和时间。我不推荐这种日期/时间格式,因为它不适用于目录D:\TL\BACKUP 中所有Data_*.xlsx 文件的字母列表。按名称排序的文件列表采用日期/时间格式yyyyMMdd_HHmmss,也会自动按日期/时间排序。

    要了解所使用的命令及其工作原理,请打开命令提示符窗口,在其中执行以下命令,并仔细阅读每个命令显示的所有帮助页面。

    • call /?
    • copy /?
    • del /?
    • echo /?
    • endlocal /?
    • exit /?
    • for /?
    • goto /?
    • if /?
    • md /?
    • set /?
    • setlocal /?
    • xcopy /?

    另见:

    【讨论】:

    • 非常感谢莫菲
    猜你喜欢
    • 2017-02-04
    • 2011-05-26
    • 1970-01-01
    • 2016-08-04
    • 2011-02-05
    • 1970-01-01
    • 2016-08-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多