
//
//
//
//
//
//
//
//
//
//
软件Tags:
文件备份器批处理文件.直接双击运行.[code]@echo off:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: 文件备份器V2.3(for WinXP only) Code by JM 2006-11-4 QQ:13132002:: 出处://www.cn-dos.net/forum/viewthread.php?tid=20747:::: 功能:1、自由指定要备份的目录(或文件)、位置、备份时间和任务名称:: 2、能检测输入是否正确:: 3、能生成备份日志:: 4、能多次添加备份任务:: 5、能批量停止指定的备份任务:: 6、能自动删除由本程序产生且不再使用的批处理程序和注册表信息:: 7、能从备份文件中恢复文件到源文件中,并保持各文件的原始属性不变:::: 原理:只有当源文件修改时间比目标文件的修改时间新时才更新文件:::: 要修改或完善的地方::::: ① 统一标记是文件还是文件夹;:: ② 禁止把文件备份到本文件夹及其子文件夹中去:::: 更新历史::::: 06.11.4:::: 增加了记录备份文件更新列表的功能,进一步完善日志功能;:::: 06.10.19:::: 因at命令只能以管理员权限运行,此次更新增加了用户权限的验证;添加了:: xcopy的/c参数,使得复制出错的时候(尽管出现这种情况的几率非常低),能备份:: 尽可能多的文件;精简了部分代码;:::: 06.9.14:::: 对提取文件属性的代码做了优化,使得生成备份批处理的效率大大提高,:: 感谢pengfei提供代码;修改了几处错误和疏漏;对代码进行分块放置以便日后:: 的维护;此为V2.3:::: 06.9.3:::: 由于上次精简过度,代码运行会出错,今天修改了一处致命错误,感谢:: pengfei的测试;增加了一些操作提示和出错检测;:::: 06.8.5:::: 添加了备份空目录的参数,精简了部分代码;:: 06.8.1:::: 实现了用同一条命令复制文件和文件夹;修正了几处错误;:: 06.7.29:::: 精简了获取属性的代码,感谢willsort提供;:: 06.7.28:: 完善了对备份后的文件进行恢复的操作,使得恢复操作对文件或者文件夹:: 都适用;此为V2.2:::: 06.7.1:: 完善了对日期的检测;:: 06.6.29:: 增加了恢复文件的功能;对生成后的文件的属性进行了调整;此为V2.1;:: 06.6.20:: 对显示各分区磁盘剩余空间的代码进行了修改,只显示磁盘的剩余空间,:: 而不会画蛇添足地显示光盘剩余空间;:: 06.6.15:: 增加了日期和时间输入错误检测功能(感谢bagpipe提供代码);:: 06.6.12:: 修改了查询各分区剩余空间的代码,当磁盘卷标名为中文时也能准确排版。:: 感谢willsort作深入分析并提供代码;当备份任务创建后,能自动打开备份后:: 的文件夹和创建日志,以便查看备份创建结果;彻底删除无用文件;精简了部:: 分代码;:: 06.6.10 :: 修正了一处错误;精简了部分代码;:: 06.6.9 :: 更改备份日志代码,将使备份日志体积减少近一半;更改了实现文件名自动:: 完成这一功能的功能键(感谢electronixtar的提醒),但需要注册表中的特定键:: 值为默认设置(有关讨论请参考//www.cn-dos.net/forum/viewthread.php?:: tid=21091&fpage=1);:: 06.6.6:: 修改了部分代码,使得当需要每天备份的功能时,避免了烦琐的输入;增加:: 了文件名自动完成的功能(感谢willsort提出设想并提供代码);此为V1.9;:: 06.6.4 :: 增加了如下功能:当保存备份文件时,如果要对文件夹进行追加或者覆盖等:: 操作,可先查看该文件夹下的内容再作决定;补充了备份风险提示;:: 06.6.3 :: 对备份后文件的保存位置这部分代码进行了修改,使得程序能自动适应备份:: 对象为文件和文件夹两种情况,使备份后文件夹的目录结构得到保持,感谢:: willsort提供代码;当备份文件即将保存到一个已经存在的目录下时,增加了允:: 许追加至该目录的选择;:: 06.6.2:: 添加和修改了了如下功能:可以选择在开机时是否自动运行备份任务程序;:: 开始运行本程序或者停止某项备份任务时,自动删除当前计划任务中不再使用的:: 备份任务程序,并删除对应的注册表键值,以减少系统垃圾;更改了备份任务程:: 序的保存位置;去除了盘符小写转换为大写的鸡肋代码;增强了路径输入为空时:: 的检测(感谢willsort提供代码);修改了几处错误;精简了部分代码,此为V1.8;:: 06.5.31 :: 在注册表中( 位置是:HKEY_LOCAL_MACHINESoftwareMicrosoftWindows:: CurrentVersionRun) 增添了开机自动运行备份程序的键值( 以备份任务名称作:: 为键值) ,尽可能减少错过备份的情况;如果更新了内容,则备份完毕后自动打:: 开备份日志;修正了几处错误;此为V1.7;:: 06.5.30 :: 完善了备份流程,在列出创建备份任务的清单时,可更改备份任务内容;在:: 创建备份任务的同时,强制启动计划任务服务,并立即作复制操作;显示各磁盘:: 分区剩余空间情况的时候,增加了显示磁盘卷标名的功能;更改了注意事项界面:: 中的前景色和背景色,使色调显得明快而柔和;:: 06.5.28 :: 增加了在每周的指定日期进行备份的功能;添加了当计划任务出错时提交报:: 告的功能;完善了日志记录功能,只有当文件更新时才会改写日志;完善了注意:: 事项中的内容;增加了删除所有计划任务的功能;此为 V1.6 ;:: 06.5.26 :: 增加了不允许把保存路径设置为与源文件路径相同、或者为源文件某一目录:: 的功能;添加了注意事项提示功能;修正了几处错误;部分代码参照中国DOS 联:: 盟论坛(//www.cn-dos.net/forum) 网友bagpipe所发帖子,使一些代码得:: 到精简;此为V1.5;:: 06.5.25 :: 增加了把备份文件的保存目录拖曳到窗口执行的功能;增加了批量停止指定:: 备份任务的功能;修改了几处错误;精简了部分代码;此为V1.4;:: 06.5.24 :: 增加了把要备份的文件拖曳到窗口执行的功能;感谢中国DOS 联盟论坛:: (//www.cn-dos.net/forum)版主willsort提供代码;此为V1.3;:: 06.5.23 :: 修正了一处关键错误,使得备份能顺利进行下去;在中国DOS 联盟论坛:: (//www.cn-dos.net/forum)版主willsort等网友的热心帮助下,增强了程:: 序输入错误检测能力,并修正了一些拼写错误,在此深表谢意;:: 06.5.22 :: 修改了显示各分区剩余空间的代码,使显示界面的框线自动适应剩余空间条:: 目下不同长度的字符;:: 06.5.21 :: 增添了停止指定备份任务的功能,使本程序的功能进一步完善;增添了将备:: 份后的文件设置为" 系统+ 只读" 属性的功能,从而在一定程度上提高了备份后:: 的文件的安全;修正了几处错误;优化了部分代码;此为V1.2;:: 06.5.20 :: 头两天的算法存在备份不完全的弊端,今天把copy命令更改为xcopy 命令,:: 从而使本程序能够备份指定目录下除空目录之外的所有文件( 包括目录之下还有:: 子目录、子目录内含有文件的文件嵌套) ,并使代码得到了精简;头两天的代码:: 生成备份任务批处理的时候,因为自动命名的程序名称是固定的,如果有不同的:: 备份任务的话,最后一次任务将把上一次的任务删除,今天把备份任务的命名改:: 为手动指定;增添了多次添加备份任务的功能;此为V1.1;:: 06.5.19 :: 增加了系统检测功能,使得该程序只能运行于XP操作系统下;编写输入错误:: 检测代码,使输入错误能得到及时更改;统一了交互界面,看上去更加美观;本:: 来想增加指定每周的某几天进行备份操作的功能,但是一直未能实现,只好暂时:: 放弃,留待下几个版本解决;优化了部分冗余代码;:: 06.5.18 :: 在对本人电脑上重要资料进行备份的时候,深感手工备份的烦琐,而网上的:: 备份软件又有诸多限制,正好本人在自学DOS 批处理编程,于是花了半天的时间:: 来构思本程序的核心功能,编写初步代码;此为V1.0;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
rem if not "%1"=="$" %comspec% /f:on /c %0 $ && goto :eof :: 屏蔽掉上一句,用TabShift+Tab可实现同样功能mode con lines=26title 文件备份器-文件备份器color 1fcls
rem =========检测系统是否支持本程序=============:check_systemver|find "XP">nul || goto system_error
rem =========检测当前用户是否具有管理员权限=============:check_popedomnet users %username%|findstr /i "*administrator">nul||goto popedom_errorcall :del_nouse
rem =======输入要备份文件的路径并检测输入是否正确=======:input_sourcemode con lines=26clscolor 1ftitle 文件备份器-请输入源文件路径echo ╭────────╮echo ╭─────────┤选择要备份的文件├─────────╮echo │ ╰────────╯ │echo │ │echo │ 本程序能把指定文件在指定时间内备份到指定位 │echo │ │echo │ 置。请把要备份的文件(或文件夹)拖曳至本窗口(推荐 │echo │ │echo │ 做法),或者手工输入需要备份文件的绝对路径或相对 │echo │ │echo │ 路径(请勿输入非法符号),然后回车确认。 │echo │ │echo │ 自动完成文件名请按TabShift+Tab,可多次选择。 │echo │ │echo │ 为了不错误删除数据,使用本软件前请查看注意 │echo │ │echo │ 事项!切记切记! (恢复文件请按 R ) │echo │ │echo ╰────────────────────────────╯echo.echo 查看注意事项请按 1 退出请按 0echo ──────────────────────────────echo 查看已存在的备份任务请按 2 echo.set source=:set /p source= 请输入要备份文件的路径:set "source=%source:"=%":: 上面这句为判断%source%中是否存在引号,有则剔除。if "%source%"==":" goto input_sourceif "%source%"=="0" exitif "%source%"=="1" goto noticeif "%source%"=="2" goto backup_taskif /i "%source%"=="r" goto revertif not exist "%source%" goto source_noexistfor %%i in ("%source%") do if "%%~fi"=="%%~di" goto forbid_to_backup:: 判断要备份的是文件还是文件夹,为以后的操作设置标志pushd "%source%">nul 2>nul && (popd & set folder=yes)||(set folder=)goto input_destination
:backup_taskclscolor 1ftitle 文件备份器-已存在的备份任务echo.atecho -------------------------------------------------------------------------------echo.echo ╔══════════════════════════════╗echo ║ 如果要停止某个备份任务,请输入该任务的ID号,然后按回车即可 ║echo ║ ║echo ║ 多个ID号之间用空格分隔,停止所有计划任务请按 A ║echo ║ ║echo ║ 退出请按 0 ,返回上一步请按除0、A和ID数字之外的任意键 ║echo ╚══════════════════════════════╝echo.set ID=set /p ID= 请输入不再需要的备份任务的ID:if "%ID%"=="0" exitif /i "%ID%"=="a" at /delete /yes && (call :del_nouse && goto backup_task):: 以下语句的作用是:如果停止了某项备份任务,则检查硬盘上由本程序生成的bat文件中,:: 不在at任务列表中的有哪些;如果有,则删除该bat,同时删除注册表中对应的字符串值;:: 如果没有,则不作任何删除操作;(for %%i in (%ID%) do at %%i /del /yes >nul 2>nul) && ( call :del_nouse goto backup_task) || goto input_source
rem =======输入文件保存路径并检测输入是否正确=======:input_destinationclscolor 1ftitle 文件备份器-请输入目标文件路径echo.echo.echo ╭────────╮echo ╭─────────┤ 选择保存位置 ├─────────╮echo │ ╰────────╯ │echo │ 操作说明: │echo │ │echo │ 请输入保存位置的绝对路径或者相对路径 │echo │ │echo │ (注意:必须在半角状态下输入冒号和反斜杠; │echo │ │echo │ 请勿输入非法的路径名符号),或者把一个已 │echo │ │echo │ 存在的文件夹拖曳至本窗口,然后回车确认。 │echo │ │echo │ ╭────────────────╮ │echo ╰─────┤ 查看各磁盘分区剩余空间请按 9 ├─────╯echo ╰────────────────╯echo.echo 返回上一步请按 1 退出请按 0echo ──────────────────────────────echo.set destination=:set /p destination= 请输入备份文件的保存路径:set "destination=%destination:"=%":: 上面这句为判断%destination%中是否存在引号,有则剔除if "%destination%"==":" goto input_destinationif "%destination%"=="0" exitif "%destination%"=="1" goto input_sourceif "%destination%"=="9" goto freesize:: 下面一句针对文件或文件夹取保存位置的文件名for /d %%i in ("%source%.*") do set destination=%destination%%%~nxifor %%i in ("%destination%") do set destination=%%~fiset subarea=%destination:~0,1%for %%i in ("%destination%") do if "%%~fi"=="%%~di" goto forbid_to_build_1echo "%destination%" | findstr /i /c:"%source%" && goto forbid_to_build_2if not exist %subarea%:nul goto subarea_noexist:: 下面一句取日志名为要备份文件(夹)的文件名for %%i in ("%source%") do set name_log=%%~niif exist "%destination%%name_log%_log.log" goto whether_addif exist "%destination%" goto whether_over
:over_writeattrib /s /d -s -h -r "%destination%*.*">nul 2>nulrd /q /s "%destination%">nul 2>nulmd "%destination%">nul 2>nul(echo.echo 备份日志)>"%destination%%name_log%_log.log"attrib /s /d +s +r "%destination%*.*">nul 2>nul
:input_dateclscolor 1ftitle 文件备份器-请输备份入日期echo ╭────────╮echo ╭─────────┤ 请输入备份日期 ├─────────╮echo │ ╰────────╯ │echo │ │echo │ 1.若在每月的某几天备份,请输入从1到31的任意 │echo │ │echo │ 数字,比如1,3,4;若只在每月1号备份,请输入"1,"; │echo │ │echo │ 2.若在每周的某几天备份,请输入星期几的代码 │echo │ │echo │ (M,T,W,Th,F,S,Su);如果指定日期较多,在查看任务 │echo │ │echo │ 列表的时候,日期一栏将用省略号显示; │echo │ │echo │ 3.数字与字母不可混用;数字行或字母行首尾均无 │echo │ │echo │ 任何符号,其间用逗号分隔;请严格按照本格式填写! │echo │ │echo ╰────────────────────────────╯echo.echo 返回上一步请按 1 退出请按 0echo ──────────────────────────────echo 每天都备份请按 Aecho.set copydate=set /p copydate= 请输入备份日期:if "%copydate%"=="" goto input_dateif "%copydate%"=="," goto input_dateif "%copydate%"=="0" exitif "%copydate%"=="1" goto input_destinationif "%copydate%"=="1," goto input_timeif /i "%copydate%"=="a" goto all_date:: 检查日期输入是否正确set num=0set char=%copydate%for /f "tokens=1 delims=," %%i in ("%char%") do ( echo "%%i"|findstr /i "M T W Th F S Su">nul && goto check_alphabetical_date|| goto check_numerical_date)
:check_alphabetical_datecall :check_alp:loop_alpset char=%char:*,=%:check_alpfor /f "tokens=1 delims=," %%i in ("%char%") do ( echo "M T W Th F S Su"|findstr /i "%%i">nul || goto date_error echo "%char%"|find ",">nul && goto loop_alp)goto input_time
:check_numerical_datecall :check_num:loop_numset /a num+=1set char=%char:*,=%:check_numfor /f "tokens=1 delims=," %%i in ("%char%") do set input=%%iif %input% GTR 31 goto date_errorif %num% GTR 30 goto date_errorecho %char%|find ",">nul || if %num% LEQ 30 goto input_time || goto date_errorgoto loop_num
:input_timeclscolor 1ftitle 文件备份器-请输入时间echo.echo ╭────────╮echo ╭─────────┤ 请输入备份时间 ├─────────╮echo │ ╰────────╯ │echo │ 操作说明: │echo │ │echo │ 请按格式输入备份时间,多个时间用空格 │echo │ │echo │ 分隔。该时间用24小时制(既从00:00到23:59) │echo │ │echo │ 的小时:分钟格式表示。 │echo │ │echo │ 例如:想分别在上午8点30分和下午4点进 │echo │ │echo │ 行备份,请在同一行输入8:30 16:00(注意:两 │echo │ │echo │ 个时间点之间有一个空格) │echo │ │echo ╰────────────────────────────╯echo.echo 返回上一步请按 1 退出请按 0echo ──────────────────────────────echo.set copytime=set /p copytime= 请输入备份时间:if "%copytime%"=="" goto input_timeif "%copytime%"=="0" exitif "%copytime%"=="1" goto input_date:: 检查时间输入是否正确for /f "tokens=*" %%i in ("%copytime%") do set char=%%icall :check_timeset num=0:backset /a num+=1set char=%char:* =%:check_timefor /f "tokens=1,2 delims=:" %%i in ("%char%") do ( if %%i GTR 24 goto time_error if %%j GTR 60 goto time_error echo %char%|find " ">nul || goto input_name)goto back
rem =======输入备份任务名称=======:input_nameclscolor 1ftitle 文件备份器-备份任务名称echo.echo ╭────────╮echo ╭─────────┤ 备份任务名称 ├─────────╮echo │ ╰────────╯ │echo │ 操作说明: │echo │ │echo │ 请输入备份任务的名称,然后回车确认。 │echo │ │echo │ 本程序将在"系统安装盘:Program Files备份 │echo │ │echo │ 任务程序"下生成"备份任务名称_backup.bat" │echo │ │echo │ 和"备份任务名称_revert.bat"这一对备份及恢 │echo │ │echo │ 复批处理。如需更改此备份任务的部分功能, │echo │ │echo │ 请用文本编辑工具对批处理文件进行编辑。 │echo │ │echo ╰────────────────────────────╯echo.echo 返回上一步请按 1 退出请按 0echo ──────────────────────────────echo.echo.set name=set /p name= 请输入备份任务的名称:if "%name%"=="" goto input_nameif "%name%"=="0" exitif "%name%"=="1" goto input_timeif exist "%ProgramFiles%备份任务程序%name%_backup.bat" goto name_exist
call :listecho ╔══════════════════════════════╗echo ║ 退出请按 0 ,返回上一步请按 1 ,放弃并开始新的备份请按 B ║echo ║ ║echo ║ 继续下一步请按除0、1和B之外的任意键 ║echo ╚══════════════════════════════╝echo.set choice=set /p choice= 请选择操作代码(0/1/B/其他键):if "%choice%"=="0" exitif "%choice%"=="1" goto input_nameif /i "%choice%"=="b" ( attrib /s /d -s -h -r "%destination%*.*">nul 2>nul rd /q /s "%destination%">nul 2>nul goto input_source)goto build_backup
:noticeclsmode con lines=40color 8etitle 文件备份器-注意事项echo.echo.echo ╔══════════════════════════════════╗echo ║ ║echo ║ 1. 当程序提示某路径已存在时,强烈建议在作出覆盖操作前先查 ║echo ║ ║echo ║ 看该目录下的内容,以免程序错误删除该目录下的所有内容,给您带 ║echo ║ ║echo ║ 灾难性的损失。备份有风险,操作请谨慎! ║echo ║ ║echo ║ 2. 路径名中,除了允许冒号和反斜杠符号紧跟盘符之外,其他位 ║echo ║ ║echo ║ 置不能再含有半角状态下的以下11个符号,分别为:、/、:、*、?、 ║echo ║ ║echo ║ "、<、>、(、)、|。输入其中任意一个符号,都会引起无法预料的错 ║echo ║ ║echo ║ 误;在本程序中,文件名的命名也应遵守以上规定! ║echo ║ ║echo ║ 3. 如果只输入"盘符+冒号"格式的路径,程序会把路径当作指定 ║echo ║ ║echo ║ 盘的当前路径来处理,而不是指定盘的根目录。比如:假设系统安装 ║echo ║ ║echo ║ 在C盘,在路径中只输入 C: ,则并不会认为是C盘根目录,而是C盘的 ║echo ║ ║echo ║ 当前路径,默认为"C:ducuments and settings当前用户名"; ║echo ║ ║echo ║ 4. 如果输入的路径不带盘符,则作为相对路径处理; ║echo ║ ║echo ║ 5. 本程序工作原理为:通过比较备份后文件与源文件的时间早晚 ║echo ║ ║echo ║ 来决定是否进行复制操作,因此,任何改动备份后文件修改时间的操 ║echo ║ ║echo ║ 作都会使程序不能及时更新源文件改动过的数据,请勿对备份后的文件 ║echo ║ ║echo ║ 进行改名、添加或删除子文件等操作! ║echo ║ ║echo ╚══════════════════════════════════╝echo.echo 按任意键返回上一步...pause>nulgoto input_source
:whether_overclscolor 0ctitle 文件备份器-路径已存在echo.echo.echo.echo.echo.echo ________________________________________________________________________________echo.echo 您输入的路径"%destination%"已经存在,覆盖还是追加?echo.echo ________________________________________________________________________________echo.echo ╔══════════════════════════════════╗echo ║ 按O覆盖,按A追加,按V查看保存目录,按 1 返回上一步,按 0 退出 ║echo ╚══════════════════════════════════╝echo.echo.set choice=set /p choice= 请选择(O/A/V/0/1): if /i "%choice%"=="o" cls && goto over_writeif /i "%choice%"=="a" goto input_dateif /i "%choice%"=="v" call :view_directory && goto whether_overif "%choice%"=="0" exitif "%choice%"=="1" goto input_destinationgoto whether_over
:whether_addclscolor 0ctitle 文件备份器-路径已存在echo.echo.echo.echo.echo.echo ________________________________________________________________________________echo.echo "%destination%"下似乎已经存在以前的备份,覆盖还是追加?echo.echo ________________________________________________________________________________echo.echo ╔═══════════════════════════════════╗echo ║ 按 V 查看保存目录,按 O 覆盖,按 A 追加,按 1 返回上一步,按 0 退出 ║echo ╚═══════════════════════════════════╝echo.echo.set choice=set /p choice= 请选择(V/O/A/0/1): if /i "%choice%"=="o" goto over_writeif /i "%choice%"=="a" cls && goto input_dateif /i "%choice%"=="v" call :view_directory && goto whether_addif "%choice%"=="0" exitif "%choice%"=="1" goto input_destinationgoto whether_add
:freesize:: 假设字符串freesize长度范围为0~7(假设硬盘最大999G,换算成以M为单位则是7位数),:: 则首先在freesize前补足7个空格,然后直接取字符串的后7个字符,即可得到右对齐排列:: 的数字freesize。同理,假设字符串volume的长度范围为0~20(卷标名最长可达32位,但是:: 为了兼顾排版的显示,只取后20位)。clscolor 2etitle 文件备份器-各分区剩余空间情况setlocal EnableDelayedExpansionecho.echo.echo ╔══════════════════════════════╗echo ║ 磁盘分区 磁盘卷标名 剩余空间(MB) ║echo ║ _____________________________________________________ ║for %%d in (C D E F G H I J K L M N O P Q R S T U V W X Y Z) do ( if exist %%d:nul ( for /f "tokens=3" %%z in ('dir /-c %%d:') do set freesize=%%z if not "!freesize!"=="0" (&
警告:运行BAT源码是一种危险的动作,如果你不熟悉,请不要尝试!