我想在批处理输出的日志行中添加时间戳。
这是我的批处理文件:
@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
这怎么实现?
更多信息:
*
是目标文件还是目录。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
。
答案 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_HHmmss
和DATE
的字符串替换将与区域相关的日期和时间重新格式化为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
将是日志的名称,请确保您在正确的目录中。