我需要备份带有日期时间戳的现有文件夹,并用文件夹内的新内容替换它(删除并重新创建)。
有人有执行此操作的脚本吗?
我尝试了以下代码,其中
%ApplicationDeploymentFolderPath% = \\servername\foldername
IF EXIST %ApplicationDeploymentFolderPath%\Release (
REM Get current date time
@echo off
For /f "tokens=1-3 delims=/ " %%a in ('date /t') do (set mydate=%%c_%%b_%%a)
For /f "tokens=1-2 delims=/:" %%a in ('time /t') do (set mytime=%%a%%b)
set backup_folder=%mydate%_%mytime%
MD %ApplicationDeploymentFolderPath%\%backup_folder%
REM Copy current folder to backup folder
Copy %ApplicationDeploymentFolderPath%\Release %ApplicationDeploymentFolderPath%\%backup_folder%
REM Delete Existing Release folder
RD %ApplicationDeploymentFolderPath%\Release /S /Q
)
MD %ApplicationDeploymentFolderPath%\Release
带有参数 date
的
命令
/T
以当前用户帐户配置的国家/地区定义的格式输出当前日期。可以通过引用动态 环境变量 DATE
(例如使用 %DATE%
)来访问完全相同的日期字符串。
带有参数 time
的
命令
/T
以当前用户帐户配置的国家/地区定义的格式输出当前时间。可以通过引用动态 环境变量 TIME
(例如使用 %TIME%
)来访问完全相同的时间字符串。
执行此命令行会发生什么?
For /f "tokens=1-3 delims=/ " %%a in ('date /t') do (set mydate=%%c_%%b_%%a)
for
分别 cmd.exe
处理批处理文件在后台启动另一个命令进程,使用 %ComSpec% /c
以及 '
之间的命令行。因此,在后台执行的操作如下,Windows 安装在 C:\Windows
:
C:\Windows\System32\cmd.exe /c date /t
在后台处理此命令进程的 STDOUT 的
command
date
的输出由执行批处理文件的 FOR 分别捕获。
使用
/
作为分配给循环变量 a
、b
和 c
的字符串分隔符,将捕获的行分成三个子字符串,这些子字符串以相反的顺序连接在一起,并使用下划线作为分隔符。
通过将
'date /t'
替换为 "%DATE%"
,可以更快地完成此任务。在这种情况下,FOR处理日期string,该日期是通过在执行FOR之前在解析此命令行时运行
cmd.exe
而扩展的。因此,无需在后台启动另一个 cmd.exe
并捕获其输出只是为了处理相同的日期 string,这使得批处理文件执行速度更快一些。
'time /t'
也是如此,可以用"%TIME%"
代替。
但是两个 FOR 循环可以通过使用字符串替换来完全优化,例如通过回答 What does %date:~-4,4%%date:~-10,2%%date:~- 7,2%_%时间:~0,2%%时间:~3,2% 意味着什么? 并且区域相关的日期和时间格式是众所周知的,例如通过在命令提示符窗口中运行:
echo %DATE% %TIME%
此命令根据配置的国家/地区以德国日期/时间格式在我的计算机上输出:
24.07.2019 20:15:29,90
在此输出中可以看出,原始代码无法在我的 Windows 计算机上使用我的帐户运行,因为日期字符串包含
.
而不是 /
,而时间字符串包含逗号。
因此,最好使用与区域无关的解决方案,如答案中详细解释的那样 为什么 %date% 在作为计划任务执行的批处理文件中产生不同的结果? 缺点是
wmic.exe
的执行时间比 长得多cmd.exe
需要将日期和时间字符串重新格式化为 yyyy_MM_dd_HHmm
。但是,批处理文件每天执行的频率很可能不是很高,因此,获取这种格式的日期/时间的执行是否需要几毫秒或大约一秒并不重要。
在这种情况下,复制整个文件夹并不是真正必要的。将其重命名为:
就足够了ren "%ApplicationDeploymentFolderPath%\release" "%backup_folder%"
如果由于未知原因无法使用命令
move
,也可以使用命令ren
。
然而,主要问题是缺乏关于如何以及何时使用延迟扩展的知识。打开 命令提示符,运行
set /?
并阅读关于 IF 和 FOR 示例延迟环境变量扩展的输出帮助解释。
这里的问题是,在执行使用
backup_folder
引用它的命令行时未定义 %backup_folder%
,因为在解析从此处开始的 %variable%
上的整个命令块时,所有出现的 (
都已被 Windows 命令处理器替换。在执行命令 IF 之前,IF 条件位于顶部,由引用的环境变量的当前值决定。
因此在现有发布文件夹上执行的是:
set backup_folder=
MD \\servername\foldername\
REM Copy current folder to backup folder
Copy \\servername\foldername\Release \\servername\foldername\
REM Delete Existing Release folder
RD \\servername\foldername\Release /S /Q
这可以通过调试批处理文件看到。
另请参阅:Windows 命令解释器 (CMD.EXE) 如何解析脚本?
解决方案是通过更改第一个 IF 条件来避免命令块。
快速区域依赖解决方案:
@echo off
setlocal EnableExtensions DisableDelayedExpansion
set "ApplicationDeploymentFolderPath=\\servername\foldername"
if not exist "%ApplicationDeploymentFolderPath%\Release\" goto CreateFolder
ren "%ApplicationDeploymentFolderPath%\Release" "%DATE:~-4%_%DATE:~-7,2%_%DATE:~-10,2%_%TIME:~0,2%%TIME:~3,2%"
:CreateFolder
md "%ApplicationDeploymentFolderPath%\Release"
endlocal
慢速区域独立解决方案:
@echo off
setlocal EnableExtensions DisableDelayedExpansion
set "ApplicationDeploymentFolderPath=\\servername\foldername"
if not exist "%ApplicationDeploymentFolderPath%\Release\" goto CreateFolder
for /F "tokens=2 delims==." %%I in ('%SystemRoot%\System32\wbem\wmic.exe OS GET LocalDateTime /VALUE') do set "BackupDateTime=%%I"
set "BackupDateTime=%BackupDateTime:~0,4%_%BackupDateTime:~4,2%_%BackupDateTime:~6,2%_%BackupDateTime:~8,4%"
ren "%ApplicationDeploymentFolderPath%\Release" "%BackupDateTime%"
:CreateFolder
md "%ApplicationDeploymentFolderPath%\Release"
endlocal
要了解所使用的命令及其工作原理,请打开命令提示符窗口,执行以下命令,并完整、仔细地阅读每个命令显示的帮助页面。
echo /?
endlocal /?
for /?
goto /?
if /?
md /?
ren /?
set /?
setlocal /?
wmic /?
wmic os /?
wmic os get /?
wmic os get localdatetime /?