Windows 为什么%date%在作为计划任务执行的批处理文件中产生不同的结果?
批处理文件正在运行Windows 为什么%date%在作为计划任务执行的批处理文件中产生不同的结果?,windows,batch-file,Windows,Batch File,批处理文件正在运行robocopy,并创建一个名为robocopyServer_%date%.txt的日志文件 手动运行批处理文件时,结果为robocopyServer_yyyy-mm-dd.txt 当批处理文件从Windows Server 2016上的计划任务运行时,结果是robocycoserver\u Tue(或一周中的任何一天),并且没有文件扩展名 此批处理文件在Windows Server 2012 R2上完美运行(手动或按计划任务)。%date%或date/t并不总是可靠的,因为它
robocopy
,并创建一个名为robocopyServer_%date%.txt的日志文件
手动运行批处理文件时,结果为robocopyServer_yyyy-mm-dd.txt
当批处理文件从Windows Server 2016上的计划任务运行时,结果是robocycoserver\u Tue
(或一周中的任何一天),并且没有文件扩展名
此批处理文件在Windows Server 2012 R2上完美运行(手动或按计划任务)。%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格式回显当前日期。环境变量字符串的格式日期和时间取决于为已用帐户定义的Windows区域设置,即,为运行批处理文件时使用的帐户配置了哪个国家,因为该国家决定了日期和时间格式
可以使用line toolWMIC获取与区域无关的日期/时间字符串
命令行
wmic OS GET LocalDateTime /VALUE
输出UTF-16小端编码,例如:
LocalDateTime=20170621095402.953000+120
有两行空行,然后是格式为yyyyMMddHHmmss.微秒±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
optionstokens=2 delims==。
仅获取20170621095402
分配给循环变量I
的原因,该变量的值分配在环境变量的旁边FileNameDate
使用字符串替换重新格式化环境变量FileNameDate
,以仅获取格式为yyyy-MM-dd
的日期字符串,该字符串输出用于验证,从而产生输出2017-06-21
使用WMIC获取本地日期/时间的优点是独立于Windows区域设置。缺点是,与在几微秒内访问的日期和时间环境变量相比,命令执行需要相当长的时间(1到2秒)
用于的命令在正确解析Unicode输出时出现问题。它将WMIC输出末尾的字节序列0D 00 0A 00 0D 00 0A 00解释为0D 0D 0A,因为两个空行为0D 0D 0A,即两个回车和一个换行。这将导致将WMIC输出末尾的最后两个空行解释为一行,并将单回车作为字符串
这通常是一个问题,因为设置“EnvironmentVariable=%%I”
的结果是%%I
在删除之前已定义的具有正确值的环境变量时扩展为仅回车
有多种解决方案可以解决的命令的Unicode解析错误。将值分配给环境变量后,可以附加&goto Label
以跳转到:Label
以退出循环,跳转到FOR循环下方的,以避免出现此问题
另一个解决方案是本代码中使用的解决方案。由于使用了WMIC选项/VALUE
,属性的名称及其值在同一行上输出。因为tokens=2
,只有当由于delims==,可以使用等号和点作为分隔符将当前行拆分为至少2个子字符串(标记)时,FOR
命令才能运行命令SET。但是WMIC输出的错误解析端用于一行,该行只包含回车符,因此没有第二个标记。由于这个原因,的命令在这里也会忽略错误解析的空行
有关UTF-16 LE编码输出的解析问题的详细信息,请参阅和
要了解所使用的命令及其工作方式,请打开命令提示符窗口,在其中执行以下命令,并非常仔细地阅读为每个命令显示的所有帮助页面
echo/?
获取/?
设置/?
wmic/?
wmic操作系统/?
wmic操作系统获取/?
wmic操作系统获取localdatetime/?
PS:有许多其他解决方案可以以特定格式获取当前日期/时间,而不依赖于为所用帐户配置的国家/地区。其中一些比wmic
的使用速度更快。所有这些替代解决方案可在以下网址的答案中找到:
您必须为用于运行任务的用户创建Windows配置文件,并在该配置文件下配置区域设置和日期格式。我遇到了与OP类似的问题,我喜欢使用wmic@Regejok的方法。下面是我处理DOS DATE返回的唯一字符串的解决方案(美国解决方案-很抱歉,没有其他地区的操作系统可供测试,但对于其他地区,可以很快重构)
我的服务器返回了%DATE%(DATE/t)的不同字符串
特例1-2018年4月7日星期三
ex.2-07/04/2018(另一个非常精细的字符串,但由于子字符串引用而导致批处理脚本失败)
我使用此脚本从日期和时间中选择子字符串来创建用于记录和归档文件的日期/时间戳变量:
原始脚本
@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
请不要判断代码。:)事情变得越来越糟了
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
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/
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
'str' var holds the value returned from DATE.
Could be formatted like ex. 1 or ex. 2, does not matter
this is string replacement, all '/' replaced with '' (null).
ex. 1 - 'Wed 07/04/2018' >> 'Wed 07042018', ex. 2 - '07/04/2018' >> '07042018'
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'
Same with day (DD), '-6' characters from end of string, length of '2'
2-digit year (YY) works as it did before (already used negative referencing)
4-digit year (CCYY) works as it did before as well
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)
string replacement to the rescue again, replace all spaces with '0',
turns the ' 9' to '09' (exactly what we want)
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