Windows 7 - 使用批处理脚本模拟Windows XP中的msbackup备份程序

backup.bat

@ECHO OFF
ECHO.
ECHO backup.bat 0.1 Copyright (c) 2010 胡争辉 (huzhengh@gmail.com)
ECHO.
ECHO 本批处理程序用于在Windows 7上实现模拟Windows XP和之前版本的msbackup.exe程序的增量备份功能。运行本批处理程序请安装7-Zip(http://www.7-zip.org/),并把7z.exe文 件所在文件夹加入系统环境变量PATH中。
ECHO.
REM 运行本批处理程序需要在相同的文件夹 中放置temp.bat和process.check.bat两个程序
REM 由于不能模拟msbackup在备份 时的卷影复制功能,因此采用在备份前检查可能涉及到的进程,以保证备份文件没有被锁定
SETLOCAL ENABLEDELAYEDEXPANSION
SET method=
SET prompt_yes=
SET ignore_dir_list=
SET process_check_list=
SET backup_dir_list=
SET target_file=
SET syntax_error=0
:SYNTAX_CHECK
IF "%1"=="" GOTO PARAMETER_CHECK
IF /I %1 EQU /full (
        IF DEFINED method (
                ECHO 您 定义了两个备份方法,%method% 和 %1,请仅定义一个
                GOTO HELP
        ) ELSE (
                SET method=%1
                SHIFT
                GOTO SYNTAX_CHECK
        )
)
IF /I %1 EQU /increment (
        IF DEFINED method (
                ECHO 您 定义了两个备份方法,%method% 和 %1,请仅定义一个
                GOTO HELP
        ) ELSE (
                SET method=%1
                SHIFT
                GOTO SYNTAX_CHECK
        )
)
IF /I %1 EQU /difference (
        IF DEFINED method (
                ECHO 您 定义了两个备份方法,%method% 和 %1,请仅定义一个
                GOTO HELP
        ) ELSE (
                SET method=%1
                SHIFT
                GOTO SYNTAX_CHECK
        )
)
IF /I %1 EQU /yes (
        SET prompt_yes=%1
        SHIFT
        GOTO SYNTAX_CHECK
)
IF /I %1 EQU /ignore (
        IF DEFINED ignore_dir_list (
                ECHO 您 定义了两个忽略的文件夹的列表文件,%ignore_dir_list% 和 %2,请仅定义一个
                GOTO HELP
        ) ELSE (
                SET ignore_dir_list=%2
                SHIFT
                SHIFT
                GOTO SYNTAX_CHECK
        )
)
IF /I %1 EQU /process (
        IF DEFINED process_check_list (
                ECHO 您 定义了两个需要关闭的进程的列表文件,%process_check_list% 和 %2,请仅定义一个
                GOTO HELP
        ) ELSE (
                SET process_check_list=%2
                SHIFT
                SHIFT
                GOTO SYNTAX_CHECK
        )
)
IF NOT DEFINED backup_dir_list (
        SET backup_dir_list=%1
        SHIFT
        GOTO SYNTAX_CHECK
)
IF NOT DEFINED target_file (
        SET target_file=%1
        SHIFT
        GOTO SYNTAX_CHECK
)
ECHO 不可识别参数:%1
SET syntax_error=1
SHIFT
GOTO SYNTAX_CHECK
:PARAMETER_CHECK
IF /I "%method%" EQU "/full" (
        SET method=full
)
IF /I "%method%" EQU "/increment" (
        SET method=increment
)
IF /I "%method%" EQU "/difference" (
        SET method=difference
)
IF NOT DEFINED method (
        ECHO 请 使用 /full 或 /increment 或 /difference 指定备份的方法
        SET syntax_error=1
)
IF /I "%prompt_yes%" EQU "/yes" (
        SET prompt_yes=yes
)
IF NOT DEFINED backup_dir_list (
        ECHO 请指定待备份的文 件夹的列表文件
        SET syntax_error=1
)
IF NOT DEFINED target_file (
        ECHO 请 指定备份的文件 名
        SET syntax_error=1
)
IF DEFINED ignore_dir_list (
        IF NOT EXIST !ignore_dir_list! (
                ECHO 您 指定的忽略指定文件夹的列表文件 !ignore_dir_list! 不存在
                SET syntax_error=1
        )
)
IF DEFINED process_check_list (
        IF NOT EXIST !process_check_list! (
                ECHO 您 指定的备份前需要关闭的进程的列表文件 !process_check_list! 不存在
                SET syntax_error=1
        )
)
IF %syntax_error%==0 GOTO BEGIN
:HELP
ECHO 语法:
ECHO backup.bat /full ^| /increment ^| /difference [/yes] [/ignore ignore_dir_list]
ECHO            [/process process_check_list] backup_dir_list target_file
ECHO.
ECHO /full                       完全备份。备份指定位置所有的文件
ECHO /increment                  增 量备份。备份自上次完全备份或增量备份以来所有更新
ECHO                             的文件
ECHO /difference                 差异备份。备份自上次完全备份以来所有更新的文件

ECHO /yes                        非 交互式运行,不显示确认提示
ECHO /ignore ignore_dir_list     指定忽略指定文件夹的列表文件,使用文本格式,每行是
ECHO                             一个待备份的文件夹的名称,例如:
ECHO                             C:\Windows
ECHO /process process_check_list 指定备份前需要关闭的进程的列表文件,使用文本格式,
ECHO                             每行是一个待关闭的进程的名称以及相应的消息说明,例
ECHO                             如:
ECHO                             qq.exe 请关闭QQ
ECHO backup_dir_list             是待备份的文件夹的列表文件,使用文本格式,每行是一
ECHO                             个待备份的文件夹的名称,例如:
ECHO                             C:\
ECHO target_file                 是备份的文件名
GOTO :EOF
:BEGIN
IF "%prompt_yes%"=="yes" (
        ECHO 非交互式运行
) ELSE (
        ECHO 交互式运行
)
IF %method%==full ECHO 完全备份
IF %method%==increment ECHO 增量备份
IF %method%==difference ECHO 差异备份
ECHO 待备份的文件夹的列表文件:%backup_dir_list%
ECHO 备份的文件名:%target_file%
IF DEFINED ignore_dir_list (
        ECHO 忽略的文件夹的列 表文件:%ignore_dir_list% 
) ELSE (
        ECHO 没有指定忽略指 定 文件夹的列表文件
)
IF DEFINED process_check_list (
        ECHO 需要关闭的进程的 列表文件:%process_check_list%
) ELSE (
        ECHO 没有指定备份前 需 要关闭的进程的列表文件
)
CALL :PROMPT_YES
IF %PROMPT_RESULT%==no GOTO :EOF
IF DEFINED process_check_list (
        ECHO 需 要关闭的进程包 括:
        FOR /F "tokens=1,2" %%i IN (%process_check_list%) DO (
                ECHO %%i
        )
        CALL :PROMPT_YES
        IF %PROMPT_RESULT%==no GOTO :EOF
        CALL process.check.bat %process_check_list%
        CALL :PROMPT_YES
        IF %PROMPT_RESULT%==no GOTO :EOF
)
ECHO 待备份的文件夹包括:
SET BACKUP_DIR_EXIST=1
FOR /F "delims="  %%i IN (%backup_dir_list%) DO (
        IF EXIST %%i (
                ECHO %%i
        ) ELSE (
                ECHO 待 备份文件夹不存在:%%i
                SET BACKUP_DIR_EXIST=0
        )
)
IF %BACKUP_DIR_EXIST%==1 (
        CALL :PROMPT_YES
        IF %PROMPT_RESULT%==no GOTO :EOF
) ELSE (
        ECHO 待备份的文件夹 的 列表文件 %backup_dir_list% 中包含不存在的文件夹,请修改
        PAUSE
        GOTO :EOF
)
IF DEFINED ignore_dir_list (
        ECHO 忽 略的文件夹包 括:
        FOR /F "delims=" %%i IN (%ignore_dir_list%) DO (
                ECHO %%i
        )
        CALL :PROMPT_YES
        IF %PROMPT_RESULT%==no GOTO :EOF
)
CALL temp.bat
SET archive_file_list=%TEMP_PATH%\archive_file_list.txt
SET temp_file_list=%TEMP_PATH%\temp_file_list.txt
SET backup_file_list=%TEMP_PATH%\backup_file_list.txt
SET zip_file_list=%TEMP_PATH%\7zip_file_list.txt
FOR /F "delims=" %%i IN (%backup_dir_list%) DO (
        ECHO 生成文件夹中待备 份文件列表: %%i
        IF %method%==full (
                DIR /A /A-D /B /ON /S "%%i" >> %archive_file_list%
        ) ELSE (
                DIR /A /AA-D /B /ON /S "%%i" >> %archive_file_list%
        )
)
IF DEFINED ignore_dir_list (
        COPY %archive_file_list% %temp_file_list%
        FOR /F "delims=" %%i IN (%ignore_dir_list%) DO (
                ECHO 过 滤指定的文件夹:%%i
                MORE %temp_file_list% | FIND /I /V "%%i" > %backup_file_list%
                COPY %backup_file_list% %temp_file_list%
        )
        DEL %temp_file_list%
) ELSE (
        COPY %archive_file_list% %backup_file_list%
)
SET SAMEDRIVE=1
SET DRIVENAME=
FOR /F "delims=" %%i IN (%backup_file_list%) DO (
        SET FILEDRIVENAME=%%i
        SET FILEDRIVENAME=!FILEDRIVENAME:~0,3!
        IF DEFINED DRIVENAME (
                IF NOT !DRIVENAME!==!FILEDRIVENAME! SET SAMEDRIVE=0
        ) ELSE (
                SET DRIVENAME=!FILEDRIVENAME!
        )
)
IF NOT %SAMEDRIVE%==1 (
        ECHO 为保持文件夹结 构,所有待备份文件请放在相同的驱动器中
        PAUSE
        GOTO :EOF
)
ECHO 经检测,所有待备份文 件位于相同的 驱动器 %DRIVENAME% 中
FOR /F "delims=" %%i IN (%backup_file_list%) DO (
        SETLOCAL DISABLEDELAYEDEXPANSION
        SET FILEPATH=%%i
        SETLOCAL ENABLEDELAYEDEXPANSION
        SET FILEPATH=!FILEPATH:~3!
        ECHO !FILEPATH!>>%zip_file_list%
        ENDLOCAL
        ENDLOCAL
)
ECHO 已创建基于驱动器 %DRIVENAME% 的待备份文件相对位置列表
ECHO 下面开始备份
CALL :PROMPT_YES
IF %PROMPT_RESULT%==no GOTO :EOF
CD /D %DRIVENAME%
7z.exe a "%target_file%" @"%zip_file_list%" -mx9 -ms=4g -mmt -scsWIN
IF NOT %method%=="difference" (
        ECHO 下面清除备份文 件 的Archive标记
        CALL :PROMPT_YES
        IF %PROMPT_RESULT%==no GOTO :EOF
        ECHO 开始清除已备份文 件的Archive标记
        SETLOCAL DISABLEDELAYEDEXPANSION
        FOR /F "delims=" %%i IN (%backup_file_list%) DO (
                ECHO 清 除已备份文件 %%i 的 Archive标记
                ATTRIB -A "%%i"
        )
        ENDLOCAL
)
ECHO 清除所有备份文件的 Archive 标记
ECHO 下面删除临时文件
CALL :PROMPT_YES
IF %PROMPT_RESULT%==no GOTO :EOF
DEL %archive_file_list%
DEL %backup_file_list%
DEL %zip_file_list%
RMDIR %TEMP_PATH%
ECHO 已删除临时文件
pause
GOTO :EOF
:PROMPT_YES
IF NOT "%prompt_yes%"=="yes" (
        SET /P confirm="您确认上述信息吗(Y/N)?"
        IF /I "!confirm:~0,1!" EQU "y" (
                SET PROMPT_RESULT=yes
        ) ELSE (
                SET PROMPT_RESULT=no
        )
)
GOTO :EOF

temp.bat

@ECHO OFF
SET TEMP_BASE=%CD%\temp
IF NOT EXIST %TEMP_BASE% (
        MKDIR %TEMP_BASE%
        ECHO 创建临时文件夹: %TEMP_BASE%
) ELSE (
        ECHO 已存在临时文件 夹: %TEMP_BASE%
)
SET TEN_HOUR=%TIME:~0,1%
IF "%TEN_HOUR%"==" " (
        SET TEN_HOUR=0
)
SET TEMP_PATH=%TEMP_BASE%\%DATE:~0,4%-%DATE:~5,2%-%DATE:~8,2%-%TEN_HOUR%%TIME:~1,1%-%TIME:~3,2%-%TIME:~6,2%
MKDIR %TEMP_PATH%
ECHO 创建临时文件夹: %TEMP_PATH%
exit /b 0

process.check.bat


@ECHO OFF
:BEFORECHECK
SET CHECKRESULT=1
FOR /F "tokens=1,2" %%i IN (%1) DO (
        TASKLIST /FI "IMAGENAME eq %%i" | FIND /I "%%i"
        IF NOT ERRORLEVEL 1 (
                SET CHECKRESULT=0
                ECHO %%j
                PAUSE
        ) ELSE (
                ECHO 没 有发现进程 %%i
        )
)
IF NOT %CHECKRESULT%==1 GOTO BEFORECHECK