在批处理作业中创建文件名作为时间戳
Posted
技术标签:
【中文标题】在批处理作业中创建文件名作为时间戳【英文标题】:Creating a file name as a timestamp in a batch job 【发布时间】:2010-11-07 01:34:09 【问题描述】:我们有一个每天运行的批处理作业,并将文件复制到拾取文件夹。我还想复制该文件并将其放入具有文件名的存档文件夹中
yyyy-MM-dd.log
在 Windows 批处理作业中最简单的方法是什么?
我基本上是在寻找这个 Unix 命令的等价物:
cp source.log `date +%F`.log
【问题讨论】:
在 Windows .bat 文件中获取所需格式的日期字符串时,看起来与建议的解决方案一样糟糕。老实说,只需检查机器上可用的编程语言,例如java、ruby、perl 或其他东西,并制作一个 5 秒的可执行文件来给你想要的东西。我不会浪费任何时间来维护 .bat 文件,该文件需要多行代码才能获得正确格式的日期。 【参考方案1】:CP source.log %DATE:~-4%-%DATE:~4,2%-%DATE:~7,2%.log
但它取决于语言环境。我不确定 %DATE%
是否已本地化,或者取决于 Windows 中为短日期指定的格式。
这是一种从this answer 提取当前日期的独立于语言环境的方法,但它取决于WMIC
和FOR /F
:
FOR /F %%A IN ('WMIC OS GET LocalDateTime ^| FINDSTR \.') DO @SET B=%%A
CP source.log %B:~0,4%-%B:~4,2%-%B:~6,2%.log
【讨论】:
需要对索引进行一些摆弄,但这似乎已经成功了。 (虽然不完全确定我理解减指数逻辑)%DATE:~-4%-%DATE:~-7,-5%-%DATE:~-10,-8%.log 如果你想使用所有正索引,你可以使用:%DATE:~10,4%-%DATE:~4,2%-%DATE:~7,2% (我只是从我以前做过的其他事情中拿来这个的,那是很久以前的事了,我不知道为什么我会按照我原来的方式做,呵呵。) 这确实会在其他语言环境中中断。在我的情况下,该命令返回2014-5.-01
(当它是2014-05-26
)。所以要非常小心,如果你发布包含这个的脚本!
使用这个时间(去除毫秒):%time:~-11,2%-%time:~-8,2%-%time:~-5,2%
【参考方案2】:
这对我有用,是一个文件名安全的解决方案(尽管它会生成 MM-dd-YYYY 格式):
C:\ set SAVESTAMP=%DATE:/=-%@%TIME::=-%
C:\ set SAVESTAMP=%SAVESTAMP: =%
C:\ set SAVESTAMP=%SAVESTAMP:,=.%.jpg
C:\ echo %SAVESTAMP%
11-04-2012@20-52-42.79.jpg
第一个命令采用 DATE 并将 /
替换为 -
,采用 TIME 并将 :
替换为 -
,并将它们组合成 DATE@TIME 格式。第二个set
语句删除所有空格,第三个set
将,
替换为.
并附加.jpg
扩展名。
上面的代码用于一个小脚本,它从安全 IP 摄像机中提取图像以进行进一步处理:
:while
set SAVESTAMP=%DATE:/=-%@%TIME::=-%
set SAVESTAMP=%SAVESTAMP: =%
set SAVESTAMP=%SAVESTAMP:,=.%.jpg
wget-1.10.2.exe --tries=0 -O %SAVESTAMP% http://admin:<password>@<ip address>:<port>/snapshot.cgi
timeout 1
GOTO while
【讨论】:
我控制台上的输出是10-12-2014@14-22-59,44.jpg
,毫秒前有一个逗号
尝试在echo
语句之前添加set SAVESTAMP=%SAVESTAMP:,=.%.jpg
。如果可行,我将更新答案。
这不是独立于语言环境的。在我的德语笔记本上返回08.06.2016@15-42-20,33.jpg
,在我的英文笔记本上返回Wed06-08-2016@15-43-45.89.jpg
。
但它仍然既不是区域设置独立,也不是创建正确的 (iso8601) 格式 yyyy-MM-dd
令人讨厌的是第一行仍然声称它是独立于语言环境的,只是在尝试之后才发现它不是......【参考方案3】:
对于仅限法语区域(法国),请小心,因为/
出现在日期中:
echo %DATE%
08/09/2013
对于我们的日志文件问题,这是我对French Locale ONLY的建议:
SETLOCAL
set LOGFILE_DATE=%DATE:~6,4%.%DATE:~3,2%.%DATE:~0,2%
set LOGFILE_TIME=%TIME:~0,2%.%TIME:~3,2%
set LOGFILE=log-%LOGFILE_DATE%-%LOGFILE_TIME%.txt
rem log-2014.05.19-22.18.txt
command > %LOGFILE%
【讨论】:
太棒了!有点难以阅读,但它确实允许按照您的意愿格式化输出。 很好,但如果你想避免使用白色字符,请小心,因为 HOUR 可以是 1 位数字:"_0:00"
(下划线字符是空格)
我得到“log-/18/.0.Sa-9.16.txt”这个答案。
@ledlogic:你的语言环境是什么?此答案适用于法语语言环境。
不工作我在 Windows 7 上得到这个 - log-/05/。 0.We-18.13.tx【参考方案4】:
因为将 %DATE%
和 %TIME%
分开并将它们重新组合在一起的想法充其量似乎很脆弱,所以这里有一个使用 powershell oneliner 的替代方案:
for /f %i in ('powershell -c "get-date -format yyyy-MM-dd--HH-mm-ss"') do @set DATETIME=%i
set LOGFILE=my-script-%DATETIME%.txt
get-date
的引用是 here,具有 .NET 样式和 UNIX 样式的格式选项。
【讨论】:
【参考方案5】:这是一个独立于语言环境的解决方案(复制到名为 SetDateTimeComponents.cmd 的文件):
@echo off
REM This script taken from the following URL:
REM http://www.winnetmag.com/windowsscripting/article/articleid/9177/windowsscripting_9177.html
REM Create the date and time elements.
for /f "tokens=1-7 delims=:/-, " %%i in ('echo exit^|cmd /q /k"prompt $d $t"') do (
for /f "tokens=2-4 delims=/-,() skip=1" %%a in ('echo.^|date') do (
set dow=%%i
set %%a=%%j
set %%b=%%k
set %%c=%%l
set hh=%%m
set min=%%n
set ss=%%o
)
)
REM Let's see the result.
echo %dow% %yy%-%mm%-%dd% @ %hh%:%min%:%ss%
我将所有 .cmd 脚本放入同一个文件夹 (%SCRIPTROOT%);任何需要日期/时间值的脚本都将调用 SetDateTimeComponents.cmd,如下例所示:
setlocal
@echo Initializing...
set SCRIPTROOT=%~dp0
set ERRLOG=C:\Oopsies.err
:: Log start time
call "%SCRIPTROOT%\SetDateTimeComponents.cmd" >nul
@echo === %dow% %yy%-%mm%-%dd% @ %hh%:%min%:%ss% : Start === >> %ERRLOG%
:: Perform some long running action and log errors to ERRLOG.
:: Log end time
call "%SCRIPTROOT%\SetDateTimeComponents.cmd" >nul
@echo === %dow% %yy%-%mm%-%dd% @ %hh%:%min%:%ss% : End === >> %ERRLOG%
如示例所示,您可以在需要更新日期/时间值时调用 SetDateTimeComponents.cmd。将时间解析脚本隐藏在它自己的 SetDateTimeComponents.cmd 文件中是隐藏丑陋细节的好方法,更重要的是,避免拼写错误。
【讨论】:
抱歉,这与语言环境无关:在我的法语 Windows 上,我得到“18 -2014- @ 13:14:43” 可以确认:不独立于语言环境。prompt $d $t
在我的系统上返回 30.05.2016 15:35:56,93。【参考方案6】:
我经常使用它,并将所有内容放入一个复制命令中。下面将 example.txt 复制为 example_YYYYMMDD_HHMMSS.txt,当然您可以修改它以适合您的首选格式。仅当文件规范中有任何空格时才需要引号。如果您想重复使用完全相同的日期/时间戳,则需要将其存储在一个变量中。
copy "path\example.txt" "path\_%date:~10,4%%date:~4,2%%date:~7,2%_%time:~0,2%%time:~3,2%%time:~6,2%.txt"
【讨论】:
【参考方案7】:这将确保输出是 2 位数的值...您可以根据自己的喜好重新排列输出并通过取消注释诊断部分进行测试。享受吧!
(我从其他论坛借了很多...)
:: ------------------ Date and Time Modifier ------------------------
@echo off
setlocal
:: THIS CODE WILL DISPLAY A 2-DIGIT TIMESTAMP FOR USE IN APPENDING FILENAMES
:: CREATE VARIABLE %TIMESTAMP%
for /f "tokens=1-8 delims=.:/-, " %%i in ('echo exit^|cmd /q /k"prompt $D $T"') do (
for /f "tokens=2-4 skip=1 delims=/-,()" %%a in ('echo.^|date') do (
set dow=%%i
set %%a=%%j
set %%b=%%k
set %%c=%%l
set hh=%%m
set min=%%n
set sec=%%o
set hsec=%%p
)
)
:: ensure that hour is always 2 digits
if %hh%==0 set hh=00
if %hh%==1 set hh=01
if %hh%==2 set hh=02
if %hh%==3 set hh=03
if %hh%==4 set hh=04
if %hh%==5 set hh=05
if %hh%==6 set hh=06
if %hh%==7 set hh=07
if %hh%==8 set hh=08
if %hh%==9 set hh=09
:: --------- TIME STAMP DIAGNOSTICS -------------------------
:: Un-comment these lines to test output
:: echo dayOfWeek = %dow%
:: echo year = %yy%
:: echo month = %mm%
:: echo day = %dd%
:: echo hour = %hh%
:: echo minute = %min%
:: echo second = %sec%
:: echo hundredthsSecond = %hsec%
:: echo.
:: echo Hello!
:: echo Today is %dow%, %mm%/%dd%.
:: echo.
:: echo.
:: echo.
:: echo.
:: pause
:: --------- END TIME STAMP DIAGNOSTICS ----------------------
:: assign timeStamp:
:: Add the date and time parameters as necessary - " yy-mm-dd-dow-min-sec-hsec "
endlocal & set timeStamp=%yy%%mm%%dd%_%hh%-%min%-%sec%
echo %timeStamp%
【讨论】:
【参考方案8】:创建一个以当前日期为文件名的文件(例如 2008-11-08.dat)
echo hello > %date%.dat
带有当前日期但不带“-”(例如 20081108.dat)
echo hello > %date:-=%.dat
【讨论】:
【参考方案9】:也许这会有所帮助:
echo off
@prompt set date=$d$_ set time=$t$h$h$h
echo some log >> %date% %time%.log
exit
或
echo off
set v=%date%.log
echo some log >> %v%
【讨论】:
不错的 Secko... %date% 值似乎有我正在寻找的东西。任何机会你都可以解释 SET 语句。 $d$_set & $t$h$h$h 到底是什么 set 是一个“SET 变量”语句。其中日期变量为 $d$_(天 + 其余时间),时间变量为 $t$h$h$h(时间 + 毫秒)。我试图展示如何使用一组变量来完成它,它可以在没有提示行的情况下正常工作。我基本上尝试这样做 set date=%YYYY%%MM%%DD% 但我在这里运行 Linux 并在 SciTE 上编译脚本所以我不知道它是否有效。对不起,如果它不起作用。 忘记添加了,$_ 是换行符。 也试试,@prompt //$d$_ $t$h$h$h$h$h$h// 请注意,这也不是独立于语言环境的。日期被格式化为当前的文化设置,在我的例子中是 DD.MM.YYYY(德语)。【参考方案10】:我编写了一个小 C 程序来打印当前时间戳(区域设置安全,没有坏字符...)。然后,我使用 FOR 命令将结果保存在环境变量中:
:: Get the timestamp
for /f %%x in ('@timestamp') do set TIMESTAMP=%%x
:: Use it to generate a filename
for /r %%x in (.\processed\*) do move "%%~x" ".\archived\%%~nx-%TIMESTAMP%%%~xx"
这是一个链接:
https://github.com/HarryPehkonen/dos-timestamp
【讨论】:
【参考方案11】:我知道这个帖子很旧,但我只想在此处添加它,因为它帮助我解决了很多问题,并且很干净。这样做的好处是您可以将它放在一个始终运行的批处理文件的循环中。服务器正常运行时间日志什么的。无论如何,这就是我使用它的目的。我希望有一天这对某人有所帮助。
@setlocal enableextensions enabledelayedexpansion
@echo off
call :timestamp freshtime freshdate
echo %freshdate% - %freshtime% - Some data >> "%freshdate - Somelog.log"
:timestamp
set hour=%time:~0,2%
if "%hour:~0,1%" == " " set hour=0%hour:~1,1%
set min=%time:~3,2%
if "%min:~0,1%" == " " set min=0%min:~1,1%
set secs=%time:~6,2%
if "%secs:~0,1%" == " " set secs=0%secs:~1,1%
set FreshTime=%hour%:%min%:%secs%
set year=%date:~-4%
set month=%date:~4,2%
if "%month:~0,1%" == " " set month=0%month:~1,1%
set day=%date:~7,2%
if "%day:~0,1%" == " " set day=0%day:~1,1%
set FreshDate=%month%.%day%.%year%
【讨论】:
这对我很有用,尽管在“.cmd”文件中,“FreshTime”变量中的冒号在用于我的“robocopy”cmdline 中的文件名时会导致错误:ERROR : Invalid Parameter #12 : "/LOG:C:\opt\Sync_08.10.2020_16:27:39.log"
As我使用破折号的修复:set FreshTime=%hour%-%min%-%secs%
【参考方案12】:
您可以简单地检测当前本地格式,并可以获取您格式中的日期,例如:
::for 30.10.2016 dd.MM.yyyy
if %date:~2,1%==. set d=%date:~-4%%date:~3,2%%date:~,2%
::for 10/30/2016 MM/dd/yyyy
if %date:~2,1%==/ set d=%date:~-4%%date:~,2%%date:~3,2%
::for 2016-10-30 yyyy-MM-dd
if %date:~4,1%==- set d=%date:~,4%%date:~5,2%%date:~-2%
::variable %d% have now value: 2016103 (yyyyMMdd)
set t=%time::=%
set t=%t:,=%
::variable %t% have now time without delimiters
cp source.log %d%_%t%.log
【讨论】:
【参考方案13】:我知道这是一篇旧帖子,但有一个更简单的答案(尽管它可能只适用于较新版本的 Windows)。只需对 DATE 和 TIME dos 命令使用 /t 参数,仅显示日期或时间,而不提示您设置,如下所示:
@echo off
echo Starting test batch file > testlog.txt
date /t >> testlog.txt
time /t >> testlog.txt
【讨论】:
【参考方案14】:1) 你可以下载GNU coreutils 附带的GNU日期
2) 您可以使用VBScript,这使得在 Windows 中的日期操作更容易:
Set objFS = CreateObject("Scripting.FileSystemObject")
strFolder = "c:\test"
Set objFolder = objFS.GetFolder(strFolder)
current = Now
mth = Month(current)
d = Day(current)
yr = Year(current)
If Len(mth) <2 Then
mth="0"&mth
End If
If Len(d) < 2 Then
d = "0"&d
End If
timestamp=yr & "-" & mth &"-"& d
For Each strFile In objFolder.Files
strFileName = strFile.Name
If InStr(strFileName,"file_name_here") > 0 Then
BaseName = objFS.GetBaseName(strFileName)
Extension = objFS.GetExtensionName(strFileName)
NewName = BaseName & "-" & timestamp & "." & Extension
strFile.Name = NewName
End If
Next
将脚本运行为:
c:\test> cscript /nologo myscript.vbs
【讨论】:
【参考方案15】:这适用于(我的)德语语言环境,应该可以根据您的需要进行调整...
forfiles /p *PATH* /m *filepattern* /c "cmd /c ren @file
%DATE:~6,4%%DATE:~3,2%%DATE:~0,2%_@file"
【讨论】:
%DATE:~6,4%%DATE:~3,2%%DATE:~0,2%
也适用于葡萄牙语位置!我的意思是 YYYYMMDD【参考方案16】:
对于用于部署的大 zip 文件,我使用四分之一小时。此页面上没有其他人之前提到过,所以我将把我的小脚本放在这里:
set /a "quarter_hours=%time:~0,2%*4 + %time:~3,2% / 15"
set "zip_file=release_%DATE:~-4%.%DATE:~4,2%.%DATE:~7,2%.%quarter_hours%.zip"
它还没有从午夜到凌晨 5 点的一刻钟归零,但它仍然可以做到这一点,因此您可以每天多次进行加盖发布,并且很少发生碰撞。
希望对您有所帮助。
【讨论】:
【参考方案17】:使用 Martin 的建议稍加调整,为文件名添加时间戳:
forfiles /p [foldername] /m rsync2.log /c "cmd /c ren @file %DATE:~6,4%%DATE:~3,2%%DATE:~0,2%_%time:~-11,2%-%time:~-8,2%-%time:~-5,2%-@file
对于 10:17:21 23/10/2019 结果是:
20191023_10-17-21-rsync2.log
【讨论】:
【参考方案18】: echo Date and Time: %date% %time%
rem 29/09/2021 10:01:34,23
set timestamp=%time: =0%
set timestamp=%timestamp::=%
set timestamp=%timestamp:,=%
set timestamp=%date:/=%%timestamp%
echo Timestamp (ddMMYYYYHHmmssms): %timestamp%
rem 2909202109543118
set timestamp=%timestamp:~4,4%%timestamp:~2,2%%timestamp:~0,2%%timestamp:~8,8%
echo Timestamp (YYYYMMddHHmmssms) %timestamp%
rem 2021092910013423
【讨论】:
【参考方案19】:请注意,您可以使用负索引更加灵活... 它将适合英语和西欧日期格式(当然可以在日期和月份之间切换位置)
回显 %DATE:~-10,2%%DATE:~-7,2%T%TIME:~0,2%%TIME:~3,2%
【讨论】:
【参考方案20】:这是一个已有 12 年历史的线程,但仍然处于活动状态,并且还没有真正独立于区域设置的仅批处理解决方案,所以这是我的 tuppence。
无论您的本地日期设置如何,这应该适用于任何 Windows 设置。为确保您获得正确的 DD MM 和 YYYY 日期部分,您需要更改注册表短日期格式。试试这个:
将当前注册表短日期格式存储在局部变量中 将注册表格式设置为 YYYYMMDD(或任何您想要的) 将当前日期存储到局部变量 将注册表重置为原始格式我将下面的脚本保存在 'YYYYMMDD.bat' 中,并根据需要调用它。
@echo off
:: Create environment variable containing current date in YYYYMMDD format.
:: Intended to be called from other batch jobs
::Save current registry date format
for /f "tokens=2*" %%a in ('reg query "HKCU\Control Panel\International" /v sShortDate^|find "REG_SZ"') do set "ssShortDate=%%b"
::Change registry date format to yyyymmdd
reg add "HKCU\Control Panel\International" /f /v sShortDate /d "yyyyMMdd" >nul
::Save current date in yyyymmdd format
set "YYYYMMDD=%date%"
::Restore original format to registry
reg add "HKCU\Control Panel\International" /f /v sShortDate /d "%ssShortDate%" >nul
echo YYYYMMDD=%YYYYMMDD%
timeout /t:1 >nul
exit /b
【讨论】:
以上是关于在批处理作业中创建文件名作为时间戳的主要内容,如果未能解决你的问题,请参考以下文章