Windows批处理命令创建备份文件夹并替换文件夹

时间:2019-07-24 16:28:31

标签: windows batch-file jenkins

我需要备份带有日期时间戳的现有文件夹,并将其替换(删除并重新创建)为文件夹内的新内容。

有人有执行此操作的脚本吗?

我尝试了以下代码,其中%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

1 个答案:

答案 0 :(得分:1)

带有参数date命令 /T以配置的国家/地区为当前用户帐户定义的格式输出当前日期。可以通过引用动态环境变量 DATE,例如使用%DATE%来访问完全相同的日期字符串。

带有参数time命令 /T以配置的国家/地区为当前用户帐户定义的格式输出当前时间。通过引用动态环境变量 TIME(例如,用%TIME%)可以访问完全相同的时间字符串。

执行此命令行会发生什么?

For /f "tokens=1-3 delims=/ " %%a in ('date /t') do (set mydate=%%c_%%b_%%a)

forcmd.exe分别处理批处理文件,是在后台使用%ComSpec% /c并在'之间使用命令行进行的另一命令处理。因此在后台执行的是在C:\Windows中安装Windows:

C:\Windows\System32\cmd.exe /c date /t

命令 date在后​​台处理此命令过程的 STDOUT 的输出分别由 FOR Windows命令处理器捕获实例执行批处理文件。

使用/作为分配给循环变量abc的字符串定界符,将捕获的行分为三个子字符串,它们以相反的顺序连接在一起下划线作为定界符。

通过将'date /t'替换为"%DATE%",可以更快地完成此任务。在这种情况下, FOR 处理在执行 FOR 之前已经在解析此命令行上运行cmd.exe的情况下扩展的日期 string 。因此,无需再在后台cmd.exe开头并捕获其输出来处理同一日期 string ,这使得批处理文件的执行速度更快。

'time /t'也可以用"%TIME%"替换。

但是,可以通过使用字符串替换来完全优化两个 FOR 循环,例如通过对What does %date:~-4,4%%date:~-10,2%%date:~-7,2%_%time:~0,2%%time:~3,2% mean?的回答进行描述,例如,通过运行在命令提示符窗口中:

echo %DATE% %TIME%

此命令会根据配置的国家/地区以德语日期/时间格式在我的计算机上输出:

24.07.2019 20:15:29,90

在此输出中可以看到,由于日期字符串包含.而不是/,并且时间字符串包含逗号,因此原始代码无法在使用我的帐户的Windows计算机上运行。

最好使用区域独立的解决方案,如%date% produces different result in batch file when run from scheduled tasks的答案中非常详细地解释。缺点是执行wmic.exe花费的时间远远超过cmd.exe将日期和时间字符串重新格式化为YYYY_MM_DD_HHMM所需的时间。但是,批处理文件很可能不是每天执行一次,因此以这种格式获取日期/时间需要花费几毫秒或一秒钟的时间,这并不重要。

在这种情况下,实际上并不需要复制整个文件夹。用以下命令重命名就足够了:

ren "%ApplicationDeploymentFolderPath%\release" "%backup_folder%"

如果由于未知原因而无法使用命令move,也可以使用命令ren

但是,主要问题是缺少有关如何以及何时使用delayed expansion的知识。打开command prompt,运行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

debugging the batch file可以看到这一点。

另请参阅:How does the Windows Command Interpreter (CMD.EXE) parse scripts?

解决方案是通过更改第一个 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 /?