批处理文件正在运行robocopy并创建robocopyServer_%date%.txt的日志文件
手动运行批处理文件时,结果为robocopyServer_yyyy-mm-dd.txt
当批处理文件从计划任务运行时,结果是robocopyServer_Tue(或一周中的任何一天) - 并且没有文件扩展名。
此批处理文件在Server 2012R2(手动或计划任务)下运行良好。
答案 0 :(得分:5)
%date%或date /t
始终不可靠,因为它取决于地区和用户设置。以下是如何获得普遍有效的日期:
for /f %%# in ('wmic os get localdatetime^|findstr .') do if "%%#" neq "" set date=%%#
set date=%date:~,4%-%date:~4,2%-%date:~6,2%
echo %date%
这将以yyyy-mm-dd格式回显当前日期。
答案 1 :(得分:1)
环境变量字符串 DATE 和 TIME 的格式取决于为已使用帐户定义的Windows区域设置。
可以使用Windows Management Instrumentation Command行工具 WMIC 获取与地区无关的日期/时间字符串。
使用命令行
wmic OS GET LocalDateTime /VALUE
输出UTF-16 Little Endian编码,例如:
LocalDateTime=20170621095402.953000+120
有两个空行,然后是当前语言环境日期/时间的行,格式为YYYYMMDDHHmmSS.microsecond±UTC偏移量,单位为分钟,另外两行为空行。
这些数据可以与批处理代码一起使用,如下所示:
@echo off
for /F "tokens=2 delims==." %%I in ('%SystemRoot%\System32\wbem\wmic.exe OS GET LocalDateTime /VALUE') do set "FileNameDate=%%I"
set "FileNameDate=%FileNameDate:~0,4%-%FileNameDate:~4,2%-%FileNameDate:~6,2%"
echo %FileNameDate%
对文件和文件夹名称感兴趣的只是等号和小数点之间的日期/时间字符串,这是使用for /F
选项tokens=2 delims==.
获取20170621095402
的原因分配给循环变量I
,其值在环境变量FileNameDate
旁边分配。
使用字符串替换重新格式化环境变量FileNameDate
以获取格式为YYYY-MM-DD
的日期字符串,输出以进行2017-06-21
的验证。
使用 WMIC 获取本地日期/时间的优势在于Windows区域设置是独立的。缺点是与使用 DATE 和 TIME 环境变量(在几微秒内访问)相比,命令执行需要相当长的时间(1到2秒)。
命令 FOR 在解析Unicode输出正确方面存在问题。它解释 WMIC 输出结束时的字节序列0D 00 0A 00 0D 00 0A 00,因为两个空行为0D 0D 0A,即两个回车和一个换行。这会导致将 WMIC 输出末尾的最后两个空行解释为单行,并将单个回车符作为字符串。
这通常是一个问题,因为set "EnvironmentVariable=%%I"
的结果是%%I
在使用正确的值删除之前已定义的环境变量时将& goto Label
扩展为回车。
有多种解决方案可以解决命令 FOR 的Unicode解析错误。一旦将值分配给环境变量,就可以附加:Label
以退出循环,跳转到 FOR 循环下面的/VALUE
,以避免遇到此问题所有
另一个解决方案是此代码中使用的解决方案。由于使用 WMIC 选项tokens=2
,属性的名称及其值将在同一行上输出。命令 FOR 运行命令 SET ,因为delims==.
仅当它可以使用等号和点将当前行拆分为至少2个子串(标记)时作为echo /?
的分隔符。但 WMIC 输出的错误解析结束是 FOR 一行只包含回车符,因此没有第二个令牌。出于这个原因,错误解析的空行在这里也被 FOR 忽略。
有关解析UTF-16 LE编码输出上 FOR 问题的详细信息,请参阅How to correct variable overwriting misbehavior when parsing output?和cmd is somehow writing Chinese text as output。
要了解使用的命令及其工作原理,请打开命令提示符窗口,执行以下命令,并完全阅读为每个命令显示的所有帮助页面。
for /?
set /?
wmic /?
wmic os /?
wmic os get /?
wmic os get localdatetime /?
false
答案 2 :(得分:1)
您必须为用于运行任务的用户创建Windows配置文件,并在该配置文件下配置区域设置和日期格式。
答案 3 :(得分:0)
我有一个与OP类似的问题,我喜欢使用wmic @Regejok的方法。这是我处理DOS DATE返回的唯一字符串的解决方案(美国解决方案-很抱歉,没有其他要测试的区域操作系统,但是可以在其他区域快速重构)。
我的服务器在%DATE%(日期/ t)返回了不同的字符串。
例如。 1-2018年7月4日星期三(完全正确的字符串)
例如。 2-07/04/2018 (另一个非常好的字符串,但由于子字符串引用而使我的批处理脚本失败)
我使用此脚本从DATE&TIME中选择子字符串来创建用于记录和归档文件的日期/时间戳变量:
原始脚本
@echo off
set HH=%TIME:~0,1%
if "%HH%"==" " goto addzero
goto hourOK
:addzero
set HH=0%TIME:~1,1%
goto end
:hourOK
set HH=%TIME:~0,2%
:end
set mn=%TIME:~3,2%
set SS=%TIME:~6,2%
set ms=%TIME:~9,2%
set MM=%DATE:~4,2%
set DD=%DATE:~7,2%
set YY=%DATE:~-2%
set CCYY=%DATE:~-4%
set dts=%CCYY%%MM%%DD%%HH%%mn%%SS%%ms%
set dateonly=%CCYY%%MM%%DD%
set monthlog=%CCYY%%MM%
@echo on
请不要判断代码。 :)会变得更好。
“ 2018年7月4日星期三”的结果:
C:\>set HH=
C:\>if " " == " " goto addzero
C:\>set HH=09
C:\>goto end
C:\>set mn=30
C:\>set SS=49
C:\>set ms=69
C:\>set MM=07
C:\>set DD=04
C:\>set YY=18
C:\>set CCYY=2018
C:\>set dts=2018070409304969
C:\>set dateonly=20180704
C:\>set monthlog=201807
这与前任非常有效。 1个字符串。我跳过了缩写的日期(星期三),一切都很好。直到我遇到了一个返回ex的服务器。 2。
'07 / 04/2018'的失败结果:
C:\>set HH=
C:\>if " " == " " goto addzero
C:\>set HH=09
C:\>goto end
C:\>set mn=31
C:\>set SS=48
C:\>set ms=59
C:\>set MM=4/
C:\>set DD=01
C:\>set YY=18
C:\>set CCYY=2018
C:\>set dts=20184/0109314859
C:\>set dateonly=20184/01
C:\>set monthlog=20184/
所有日期/时间戳均包含“ /”(文件命名失败)。这都是由于DATE字符串差异和子字符串引用引起的。时间很好。 即使在月份(MM)和日期(DD)字符串中出现故障,我也注意到2位数和4位数的Year vars很好(YY&CCYY)。怎么样?负引用。 这成为我最终脚本的最大修复方法。以及字符串替换。
我的新脚本 (我仍然喜欢使用wmic的方法,这是另一种允许仅使用DOS的DATE返回2种不同返回类型的方法)
01 @echo off
02 set str=%DATE%
03 set str=%str:/=%
04
05 set MM=%str:~-8,2%
06 set DD=%str:~-6,2%
07 set YY=%str:~-2%
08 set CCYY=%str:~-4%
09
10 set HH=%TIME:~0,2%
11 set HH=%HH: =0%
12 set mn=%TIME:~3,2%
13 set SS=%TIME:~6,2%
14 set ms=%TIME:~9,2%
15
16 set _dts=%CCYY%%MM%%DD%%HH%%mn%%SS%%ms%
17 set _dateonly=%CCYY%%MM%%DD%
18 set _monthlog=%CCYY%%MM%
19 @echo on
注释:
第2行:
'str' var holds the value returned from DATE.
Could be formatted like ex. 1 or ex. 2, does not matter
第3行:
this is string replacement, all '/' replaced with '' (null).
ex. 1 - 'Wed 07/04/2018' >> 'Wed 07042018', ex. 2 - '07/04/2018' >> '07042018'
第5行:
this is where negative referencing made both date strings equal (in a sense),
month (MM) starts at '-8' characters from the end of the string in both
examples, length of '2'
第6行:
Same with day (DD), '-6' characters from end of string, length of '2'
第7行:
2-digit year (YY) works as it did before (already used negative referencing)
第8行:
4-digit year (CCYY) works as it did before as well
第10行:
TIME always returns 2-digits in its hour (HH) position, it just doesn't have
a leading '0' if less than 10, what it does return is a leading space
i.e. %TIME:~0,2% will return ' 9' for 9:00 AM (not desired for date/timestamps)
第11行:
string replacement to the rescue again, replace all spaces with '0',
turns the ' 9' to '09' (exactly what we want)
第12行:
minutes, seconds, milliseconds all work as they did previously, using
sub-strings to avoid the colons (':') & the period ('.') in the time stamp
i.e. 10:01:26.29
新脚本的结果:
C:\>set str=07/04/2018
C:\>set str=07042018
C:\>set MM=07
C:\>set DD=04
C:\>set YY=18
C:\>set CCYY=2018
C:\>set HH= 9
C:\>set HH=09
C:\>set mn=42
C:\>set SS=26
C:\>set ms=48
C:\>set _dts=2018070409422648
C:\>set _dateonly=20180704
C:\>set _monthlog=201807
C:\>set str=Wed 07/04/2018
C:\>set str=Wed 07042018
C:\>set MM=07
C:\>set DD=04
C:\>set YY=18
C:\>set CCYY=2018
C:\>set HH=10
C:\>set HH=10
C:\>set mn=50
C:\>set SS=55
C:\>set ms=48
C:\>set dts=2018070410505548
C:\>set dateonly=20180704
C:\>set monthlog=201807
希望这会有所帮助。这不是唯一的,也不是地球崩溃,只是另一种方式。