如何从批处理文件输出中向日志文件中的日志行添加时间戳?

时间:2018-08-31 05:56:24

标签: batch-file timestamp logfile

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

这是我的批处理文件:

@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. 使用
  3. 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

4 个答案:

答案 0 :(得分:1)

您可以使用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.

答案 1 :(得分:1)

您仅XCopy个文件,因此您知道成功输出的最后一行将是与语言相关的字符串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 :(得分:0)

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

@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

通过使用动态环境变量YYYYMMDD_HHmmssDATE的字符串替换将与区域相关的日期和时间重新格式化为TIME,例如,关于{{3} }对于慢得多但与地区无关的解决方案,要以特定格式获取日期/时间,请参见What does %date:~-4,4%%date:~-10,2%%date:~-7,2%_%time:~0,2%%time:~3,2% mean?上的答案。

将格式为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

也请阅读有关%date% produces different result in batch file when run from Scheduled Tasks in Server 2016的Microsoft文章,以获取2>nul的解释。当Windows命令解释器在执行命令之前处理此命令行时,重定向操作符>必须在 FOR 命令行上使用脱字符号^进行转义,才能被解释为文字字符。 FOR ,它将在后台启动的单独命令进程中执行嵌入式xcopy命令行。

目标文件名末尾的星号*应该在第二个参数字符串的双引号内,并且不能在外,因为否则cmd.exe分别xcopy.exe必须纠正这种错误的语法。 / p>

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

通常,有更好的方法来避免在使用新文件名复制单个文件的情况下 XCOPY 请求的提示停止。可以首先将回答提示的字母输出到 STDOUT ,并重定向为处理 XCOPY 命令的 STDIN ,因为在{{3 }}。

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

此处的目标是在此命令过程中,也在后台命令过程中输出所有带有 XCOPY 输出的标准文件的行,但是输出的最后一行的摘要信息将不同带有日期/时间的通配符格式,一个空格,一个冒号和另一个空格。

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

只有具有完整限定文件名且以驱动器号和冒号开头的行才包含冒号。在这样的行上,驱动器号被分配给由I指定的指定循环变量tokens=1。在第一个冒号之后的文件名行的其余部分被分配,而没有根据Using Command Redirection Operators进一步拆分到下一个循环变量到循环变量J,这里是驱动器号后冒号后面的所有内容。

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

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

请注意,此方法仅适用于从具有驱动器号的驱动器复制文件。对于具有batch file asks for file or folder路径的源文件,可能需要使用其他方法。

实际上,即使从/到网络驱​​动器或指定了源/目标文件名,也可以使用命令 COPY 而不是 XCOPY 来轻松复制单个文件。 UNC路径。 COPY 还有/V/Y甚至/Z之类的选项,如 XCOPY COPY 不会创建像 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(如果现在确实需要)。我不建议使用此日期/时间格式,因为它在目录Data_*.xlsx中所有D:\TL\BACKUP文件的字母列表中并不理想。按名称排序的文件列表的日期/时间格式为YYYYMMDD_HHmmss,也会自动按日期/时间排序。

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

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

另请参阅:

答案 3 :(得分:0)

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

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

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