这受another post on Arqade启发,关于如何使用批处理脚本备份某些文件。
以下块使用当前日期/时间字符串创建变量:
REM -- Get the current date/time stamp
set DS=%date%
set TS=%time: =0%
set mm=%DS:~4,2%
set dd=%DS:~7,2%
set yyyy=%DS:~10,4%
set hh=%TS:~0,2%
set min=%TS:~3,2%
set ss=%TS:~6,2%
set ms=%TS:~9,2%
set DT_STAMP=%yyyy%-%mm%-%dd%_%hh%.%min%.%ss%
作为脚本编写者,将这些内容合并为一行通常很方便。然而,在这种情况下,如果不是不可能的话,将其冷凝成单线是非常困难的。
似乎没有办法将多个set
命令放在一行上。使用&
或&&
分隔命令可以正常工作,但右侧的命令不能依赖于先前在同一行上设置的变量。
另外,请注意time
变量必须如何将spaces
替换为零0
。似乎没有办法让字符串替换和在同一行上获取子字符串。
有什么方法可以将它降到一行吗?我能得到的最接近的是两行:
set DS=%date% && set TS=%time: =0%
set DT_STAMP=%DS:~10,4%-%DS:~4,2%-%DS:~7,2%_%TS:~0,2%.%TS:~3,2%.%TS:~6,2%
这已经收集了一些好的答案;请允许我澄清接受的答案必须具备的内容:
答案 0 :(得分:3)
使用FOR / F语句很简单,但是正如npocmaka已经说过的那样,它取决于本地化。
我认为您的日期/时间看起来像
Fri 09/14/2018
8:15:46.12
那么这行得通
for /F "tokens=1-7 delims=/:,. " %%1 in ("%date% %time: =0%") do set DT_STAMP=%%4-%%2-%%3_%%5.%%6.%%7
但是对于德国本地化,您需要
for /F "tokens=1-7 delims=/:,. " %%1 in ("%date% %time: =0%") do set DT_STAMP=%%3-%%2-%%1_%%4h%%5m%%6s
带有批处理宏的解决方案
您可以构建一个批处理宏,使用宏更具可读性,但是宏本身要复杂一些
使用宏,它将当前时间戳分配给变量myDT1:
%@AssignTimeStamp% myDT1
echo %myDT1%
宏的定义(在定义宏时必须禁用延迟扩展):
REM *** Macro definition, be sure that there aren't any trailing whitespaces
set ^"LF=^
%= This creates a variable containing a single linefeed (0x0A) character =%
^"
:: Define %\M% to effectively issue a newline with line continuation
set ^"\M=^^^%LF%%LF%^%LF%%LF%^^"
set @AssignTimeStamp=for %%. in (1 2) do if %%.==2 (%\M%
%= The next line builds the timestamp =%%\M%
for /F "tokens=1-7 delims=/:,. " %%1 in ("%date% %time: =0%") do set timestamp=%%4-%%2-%%3_%%5h%%6m%%7s%\M%
%= When a variable name was give then store the timestamp there, else output the timestamp =%%\M%
for /F "tokens=1,2 delims=, " %%1 in ("#,!argv!") do ( %\M%
for %%V in (!timestamp!) do endlocal^&if "%%~2" neq "" (set "%%2=%%V") else echo ##%%V%\M%
)%\M%
) else setlocal enableDelayedExpansion^&set argv=,
答案 1 :(得分:2)
是的,你可以 - delayed expansion:
setlocal enableDelayedExpansion&set "DS=%date%"&& set "TS=%time: =0%"&set "DT_STAMP=!DS:~10,4!-!DS:~4,2!-!DS:~7,2!_!TS:~0,2!.!TS:~3,2!.!TS:~6,2!"
但这是格式化日期时间的一种不好的方式,因为它取决于本地化设置。为什么要在一行上执行此操作?对于与设置无关的方法检查this。
答案 2 :(得分:2)
您似乎想要一个类似ISO-8601的格式化日期。无论系统的区域/文化设置如何,这都将生成格式正确的日期。如果在.bat脚本文件中使用它,请加倍%
变量上的d
个字符。
FOR /F %d IN ('powershell -NoLogo -NoProfile -Command Get-Date -UFormat %Y-%m-%d_%H.%M.%S') DO (SET "DT_STAMP=%d")
或者,直接在PowerShell中使用:
$DT_STAMP = Get-Date -UFormat %Y-%m-%d_%H.%M.%S
答案 3 :(得分:2)
可以使用命令行中的日期和时间为region/country dependent的动态环境变量DATE
和TIME
根据要求完成此操作:
@set "DT_STAMP=%DATE:~10,4%-%DATE:~4,2%-%DATE:~7,2%_%TIME:~0,2%.%TIME:~3,2%.%TIME:~6,2%" & call set "DT_STAMP=%%DT_STAMP: =0%%"
此命令行期望DATE
具有日期字符串,例如Sat 09/15/2018
,而TIME
具有时间字符串,例如 4:18:23,56
,并且采用24小时格式。 / p>
对于给定的示例日期和时间字符串,环境变量DT_STAMP
的值为2018-09-15_04.18.23
。
最好使用命令行:
@set "DT_STAMP=%DATE:~-4%-%DATE:~-10,2%-%DATE:~-7,2%_%TIME:~0,2%.%TIME:~3,2%.%TIME:~6,2%" & call set "DT_STAMP=%%DT_STAMP: =0%%"
第二个版本的优点是日期字符串是否以工作日开头并不重要。但是日期字符串必须具有MM/DD/YYYY
(MDY)格式,并带有/
或.
或-
之类的任何分隔符。
但是大多数国家/地区使用DD.MM.YYY
(DMY)(具有不同的分隔符),这需要进行一些小的修改:
@set "DT_STAMP=%DATE:~-4%-%DATE:~-7,2%-%DATE:~-10,2%_%TIME:~0,2%.%TIME:~3,2%.%TIME:~6,2%" & call set "DT_STAMP=%%DT_STAMP: =0%%"
另请参阅What does %date:~-4,4%%date:~-10,2%%date:~-7,2%_%time:~0,2%%time:~3,2% mean?
使用第二个 SET 命令在同一命令行上用0
替换所有空格,该命令引用了环境变量DT_STAMP
和%%
而不是%
。
在执行第一个 SET 命令之前,在将命令行解析为%%
的过程中,两个cmd.exe
被%
替换。因此,最终执行的命令行例如:
@set "DT_STAMP=2018-09-15_ 4.18.23" & call set "DT_STAMP=%DT_STAMP: =0%"
使用 CALL 会导致&
之后对运算符cmd.exe
之后的命令行部分进行第二次解析。因此,第二个 SET 具有参数"DT_STAMP=2018-09-15_04.18.23"
作为参数,并且最终为环境变量DT_STAMP
分配了所需的日期/时间字符串。
但是更好的方法是以所需格式获取当前本地日期/时间字符串,而与区域/国家/地区设置无关,这也可以通过单个命令行进行:
@for /F "tokens=2 delims==." %%I in ('%SystemRoot%\System32\wbem\wmic.exe OS GET LocalDateTime /VALUE') do @set "DT_STAMP=%%I" & call set "DT_STAMP=%%DT_STAMP:~0,4%%-%%DT_STAMP:~4,2%%-%%DT_STAMP:~6,2%%_%%DT_STAMP:~8,2%%.%%DT_STAMP:~10,2%%.%%DT_STAMP:~12,2%%"
它使用 WMIC 来获取当前本地日期/时间区域的独立性,并再次使用 CALL 和 SET 重新格式化日期/时间字符串包含所需格式的空格。
有关此命令行如何处理 WMIC 输出的说明,请参见我在%date% produces different result in batch file when run from Scheduled Tasks in Server 2016上的回答。
顺便说一句:.
通常用作文件名和文件扩展名之间的分隔符。因此,最好在小时和分钟之间以及分钟和秒之间使用-
而不是.
。
另一个注意事项:call
之后的命令也可以是任何其他直接使用日期/时间字符串的命令,例如,在文件/文件夹名称/路径中使用的命令。