|
namejm
荣誉版主
batch fan
积分 5226
发帖 1737
注册 2006-3-10 来自 成都
状态 离线
|
『楼 主』:
[原创][XP]文件备份器V2.4(Final) [07-4-8更新]
当前讨论:
本人机子为XP系统,要备份的文件为"c:\program files\家易理财 2004\date"文件夹下的文件,该文件夹下只有几个.mdf格式(该软件自带格式)的数据文件,保存到"E:\家易理财数据备份"文件夹下,备份的时间为每天的12:00 19:00 22:00。今天21点的时候打开电脑,提示说备份服务不正常,22点之前改动了date文件夹下的文件,22点之后查看"E:\家易理财数据备份"下的日志,发现没有备份记录,再查看该文件夹下的文件,没有任何改动,打开任务管理器查看进程,cmd.exe和xcopy.exe一直在运行,在C:\WINDOWS\Tasks下查看状态,At1空白(12:40的时候已经执行了备份动作),At2为"错过",At3为"正在运行",请问这是什么原因?
这个问题已经解决,解决办法见6楼的描述。
经过N次修改的备份程序完整代码如下。
已知的问题:
1、CMD复制某些文件时会出错,会导致文件不能完整地备份,原因正在查找中,不过几率相当低;
2、暂无,期待大家更多的测试反馈
@echo off
:: 文件备份器V2.4(for WinXP only) Code by JM Renew on 2007-4-8 QQ:13132002
:: Thanks to willsort、bagpipe、pengfei……
:: 出处:http://www.cn-dos.net/forum/viewthread.php?tid=20747
::
:: 功能:1、自由指定要备份的目录(或文件)、位置、备份时间和任务名称
:: 2、能检测输入是否正确
:: 3、能生成备份日志
:: 4、能多次添加备份任务
:: 5、能批量停止指定的备份任务
:: 6、能自动删除由本程序产生且不再使用的批处理程序和注册表信息
::
:: 原理:只有当源文件修改时间比目标文件的修改时间新时才更新文件
:: if not "%1"=="$" %comspec% /f:on /c %0 $ && goto :eof
:: 屏蔽掉上一句,用Tab\Shift+Tab可实现同样功能
mode con lines=26
title 文件备份器
color 1f
cls
rem =========检测系统是否支持本程序=============
:check_system
ver|find "XP">nul || goto system_error
rem =========检测当前用户是否具有管理员权限=============
:check_popedom
net users %username%|findstr /i "\*administrator ">nul || goto popedom_error
rem =======输入要备份文件的路径并检测输入是否正确=======
:input_source
mode con lines=26
cls
color 1f
title 文件备份器-请输入源文件路径
echo ╭────────╮
echo ╭─────────┤选择要备份的文件├─────────╮
echo │ ╰────────╯ │
echo │ │
echo │ 本程序能把指定文件在指定时间内备份到指定位 │
echo │ │
echo │ 置。请把要备份的文件(或文件夹)拖曳至本窗口(推荐 │
echo │ │
echo │ 做法),或者手工输入需要备份文件的绝对路径或相对 │
echo │ │
echo │ 路径(请勿输入非法符号),然后回车确认。 │
echo │ │
echo │ 自动完成文件名请按Tab\Shift+Tab,可多次选择。 │
echo │ │
echo │ 为了不错误删除数据,使用本软件前请查看注意 │
echo │ │
echo │ 事项!切记切记! (查看备份脚本程序请按 V ) │
echo │ │
echo ╰────────────────────────────╯
echo.
echo 查看注意事项请按 1 退出请按 0
echo ──────────────────────────────
echo 查看已存在的备份任务请按 2
echo.
set source=:
:: 上面这句为后面去除引号做铺垫,冒号绝对不能省略;否则,当输入为空时按下回车会出错。
set /p source= 请输入要备份文件的路径:
set "source=%source:"=%"
:: 上面这句为判断%source%中是否存在引号,有则剔除。
if "%source%"==":" goto input_source
if "%source%"=="0" exit
if "%source%"=="1" goto notice
if "%source%"=="2" goto backup_tasks
if /i "%source%"=="v" goto view_batch
if not exist "%source%" goto source_noexist
for %%i in ("%source%") do if "%%~fi"=="%%~di\" goto forbid_to_backup
:: 判断要备份的是文件还是文件夹,为以后的xcopy操作设置标志
pushd "%source%" 2>nul && (popd & set folder=yes) || (set folder=)
goto input_destination
:backup_tasks
cls
color 1f
title 文件备份器-已存在的备份任务
echo.
at
echo -------------------------------------------------------------------------------
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" exit
if /i "%ID%"=="a" (
at /del /yes
call :del_unused
goto backup_tasks
)
:: 以下语句的作用是:如果停止了某项备份任务,则检查硬盘上由本程序生成的cmd文件中,
:: 不在at任务列表中的有哪些;如果有,则删除该cmd,同时删除注册表中对应的字符串值;
:: 如果没有,则不作任何删除操作;
(for %%i in (%ID%) do at %%i /del /yes 2>nul) && (
call :del_unused
goto backup_tasks
) || goto input_source
rem =======输入文件保存路径并检测输入是否正确=======
:input_destination
cls
color 1f
title 文件备份器-请输入目标文件路径
echo.
echo.
echo ╭────────╮
echo ╭─────────┤ 选择保存位置 ├─────────╮
echo │ ╰────────╯ │
echo │ 操作说明: │
echo │ │
echo │ 请输入保存位置的绝对路径或者相对路径 │
echo │ │
echo │ (注意:必须在半角状态下输入冒号和反斜杠; │
echo │ │
echo │ 请勿输入非法的路径名符号),或者把一个已 │
echo │ │
echo │ 存在的文件夹拖曳至本窗口,然后回车确认。 │
echo │ │
echo │ ╭────────────────╮ │
echo ╰─────┤ 查看各磁盘分区剩余空间请按 9 ├─────╯
echo ╰────────────────╯
echo.
echo 返回上一步请按 1 退出请按 0
echo ──────────────────────────────
echo.
set destination=:
set /p destination= 请输入备份文件的保存路径:
set "destination=%destination:"=%"
:: 上面这句为判断%destination%中是否存在引号,有则剔除
if "%destination%"==":" goto input_destination
if "%destination%"=="0" exit
if "%destination%"=="1" goto input_source
if "%destination%"=="9" goto freesize
:: 取文件夹保存位置完整路径或者文件保存位置的目录名
for /d %%i in ("%source%.*") do set "destination=%destination%\%%~nxi"
for %%i in ("%destination%") do set "destination=%%~fi"
set "subarea=%destination:~0,1%"
for %%i in ("%destination%") do if "%%~fi"=="%%~di\" goto forbid_to_build_1
echo "%destination%" | findstr /i /c:"%source%">nul && goto forbid_to_build_2
if not exist %subarea%:\ goto subarea_noexist
:: 下面一句取日志名为要备份文件(夹)的文件名
for %%i in ("%source%") do set "name_log=%%~ni"
if exist "%destination%\%name_log%_log.log" goto whether_add
if exist "%destination%" goto whether_over
:over_write
rd /q /s "%destination%" 2>nul
md "%destination%" 2>nul
(echo.
echo 备份日志)>"%destination%\%name_log%_log.log"
:input_date
cls
color 1f
title 文件备份器-请输备份入日期
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 退出请按 0
echo ──────────────────────────────
echo 每天都备份请按 A
echo.
set copydate=
set /p copydate= 请输入备份日期:
if "%copydate%"=="" goto input_date
if "%copydate%"=="," goto input_date
if "%copydate%"=="0" exit
if "%copydate%"=="1" goto input_destination
if "%copydate%"=="1," goto input_time
if /i "%copydate%"=="a" goto all_date
:: 检查日期输入是否正确
set /a num="%copydate:~0,1%" 2>nul&&(
goto check_numerical_date) || (
goto check_alphabetical_date
)
:check_alphabetical_date
for %%i in (%copydate%) do (
echo "M T W Th F S Su"|findstr /i "%%i">nul || goto date_error
)
goto input_time
:check_numerical_date
for %%i in (%copydate%) do (
if %%i lss 1 goto date_error
if %%i gtr 31 goto date_error
)
:input_time
cls
color 1f
title 文件备份器-请输入时间
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 退出请按 0
echo ──────────────────────────────
echo.
set copytime=
set /p copytime= 请输入备份时间:
if "%copytime%"=="" goto input_time
if "%copytime%"=="0" exit
if "%copytime%"=="1" goto input_date
:: 检查时间输入是否正确
for %%i in (%copytime%) do (
for /f "tokens=1* delims=:" %%j in (%%i) do (
if %%j lss 0 goto time_error
if %%j gtr 23 goto time_error
if %%k lss 0 goto time_error
if %%k gtr 59 goto time_error
)
)
rem =======输入备份任务名称=======
:input_name
cls
color 1f
title 文件备份器-备份任务名称
echo.
echo ╭────────╮
echo ╭─────────┤ 备份任务名称 ├─────────╮
echo │ ╰────────╯ │
echo │ 操作说明: │
echo │ │
echo │ 请输入备份任务的名称,然后回车确认。 │
echo │ │
echo │ 本程序将在"系统安装盘:\Program Files\备份 │
echo │ │
echo │ 任务程序"下生成"备份任务名称_backup.cmd" │
echo │ │
echo │ 这一备份批处理脚本程序。如需更改此备份任务 │
echo │ │
echo │ 的部分功能,请用文本编辑工具对批处理文件 │
echo │ │
echo │ 进行编辑。 │
echo │ │
echo ╰────────────────────────────╯
echo.
echo 返回上一步请按 1 退出请按 0
echo ──────────────────────────────
echo.&echo.
set name=
set /p name= 请输入备份任务的名称:
if "%name%"=="" goto input_name
if "%name%"=="0" exit
if "%name%"=="1" goto input_time
if exist "%ProgramFiles%\备份任务程序\%name%_backup.cmd" goto name_exist
call :list
echo ╔══════════════════════════════╗
echo ║ 退出请按 0 ,返回上一步请按 1 ,放弃并开始新的备份请按 B ║
echo ║ ║
echo ║ 继续下一步请按除0、1和B之外的任意键 ║
echo ╚══════════════════════════════╝
echo.
set choice=
set /p choice= 请选择操作代码(0/1/B/其他键):
if "%choice%"=="0" exit
if "%choice%"=="1" goto input_name
if /i "%choice%"=="b" (
attrib /s /d -s -h -r "%destination%\*.*" 2>nul
rd /q /s "%destination%" 2>nul
goto input_source
)
goto build_backup
:notice
cls
mode con lines=40
color 8e
title 文件备份器-注意事项
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>nul
goto input_source
:whether_over
cls
color 0c
title 文件备份器-路径已存在
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_write
if /i "%choice%"=="a" goto input_date
if /i "%choice%"=="v" call :view_directory && goto whether_over
if "%choice%"=="0" exit
if "%choice%"=="1" goto input_destination
goto whether_over
:whether_add
cls
color 0c
title 文件备份器-备份文件已存在
echo.&echo.&echo.&echo.&echo.
echo ________________________________________________________________________________
echo.
echo "%destination%"
echo.
echo 下似乎已经存在以前的备份文件,覆盖此目录还是追加到此目录?
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_write
if /i "%choice%"=="a" cls && goto input_date
if /i "%choice%"=="v" call :view_directory && goto whether_add
if "%choice%"=="0" exit
if "%choice%"=="1" goto input_destination
goto whether_add
:freesize
:: 假设字符串freesize长度范围为0~7(假设硬盘最大999G,换算成以M为单位则是7位数),
:: 则首先在freesize前补足7个空格,然后直接取字符串的后7个字符,即可得到右对齐排列
:: 的数字freesize。同理,假设字符串volume的长度范围为0~20(卷标名最长可达32位,但是
:: 为了兼顾排版的显示,只取后20位)。
:: 主体代码由willsort提供
cls
color 2e
title 文件备份器-各分区剩余空间情况
setlocal EnableDelayedExpansion
echo.&echo.
echo ╔══════════════════════════════╗
echo ║ 磁盘分区 磁盘卷标名 剩余空间(MB) ║
echo ║ _____________________________________________________ ║
for %%i 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 %%i:\ (
for /f "tokens=3" %%j in ('dir /-c %%i:\') do set freesize=%%j
if not "!freesize!"=="0" (
set /a freesize=!freesize:~0,-3!/1049
set freesize= !freesize!
set freesize=!freesize:~-7!
for /f "tokens=3*" %%k in ('vol %%i:') do set volume=%%l
set volume= !volume!
set volume=!volume:~-20!
echo ║ %%i: !volume! !freesize! ║
)
)
)
endlocal
echo ╚══════════════════════════════╝
echo.&echo.&echo.&echo.
echo 按任意键返回上一步...
pause>nul
goto input_destination
rem ========创建备份任务脚本程序,要考虑到生成多个批处理文件的情况=============
:build_backup
call :list
title 文件备份器-正在生成备份程序...
md "%ProgramFiles%\备份任务程序" 2>nul
set batch_directory=%ProgramFiles%\备份任务程序
attrib /s /d -r -h -s "%batch_directory%\*.*" 2>nul
:: 因为把所有的批处理内容只用一句 >"%batch_directory%\%name%_backup.cmd" 来接收,
:: 所以其中的括号都要用 ^ 来转义
(
echo @echo off
echo mode con cols=35 lines=10
echo color 1f
echo title 文件备份器-"%name%_backup"
echo :: 本程序由"文件备份器V2.4"生成 Code by JM Renew on 2007-4-8 QQ:13132002
echo :: build on %date% %time:~0,-3% by %username%
echo.
echo :: 原理:比较原始文件和备份文件修改日期的早晚,如果原始文件修改时间晚于备份文件,
echo :: 则复制原始文件覆盖备份文件;如果时间没差别,则不作任何处理。
echo.
echo if not exist "%source%" ^(
echo title 文件丢失
echo color 0c
echo echo.
echo echo ___________________________________
echo echo.
echo echo 文件"%source%"
echo echo.
echo ecoh 不存在,可能已被改名、移动或者删除
echo echo.
echo echo ___________________________________
echo ping -n 5 127.1>nul
echo exit^)
echo md "%destination%" 2^>nul
)>"%batch_directory%\%name%_backup.cmd"
set xcopy_parameter=
if "%folder%"=="yes" (set xcopy_parameter=/e /s) else (goto file_backup)
(
echo set times=
echo setlocal enabledelayedexpansion
echo for /f "delims=" %%%%i in ^('xcopy /c /d /h /i /g /r %xcopy_parameter% /x /y "%source%" "%destination%"'^) do ^(
echo if "%%%%i"=="复制了 0 个文件" ^(exit^) else ^(
echo if not defined times call :head
echo if ^^!file_time^^! lss %%%%~ti set file_time=%%%%~ti^&set file_route=%%%%~dpnxi
echo if not "%%%%~ti"=="" ^(echo %%%%~dpnxi %%%%~ti^>^>"%destination%\%name_log%_log.log"
echo ^) else ^(echo.^&echo %%%%i^)^>^>"%destination%\%name_log%_log.log"
echo ^)
echo if "%%%%i"=="复制了 1 个文件" goto end
echo ^)
echo ^(
echo echo.
echo echo 最后更新的文件是:%%file_route%% ,更新操作发生在 %%file_time%% 。
echo ^)^>^>"%destination%\%name_log%_log.log"
echo :end
echo start "" "%destination%\%name_log%_log.log"
echo goto :eof
echo.
)>>"%batch_directory%\%name%_backup.cmd"
call :build_head
goto add_to_reg
:file_backup
(
echo xcopy /c /d /h /i /g /q /x /y "%source%" "%destination%"^|findstr /b /e /c:"复制了 0 个文件"^>nul^&^&goto :eof
echo echo.^>^>"%destination%\%name_log%_log.log"
echo for /f "skip=1 tokens=1,2" %%%%i in ^('dir /a-d /tw "%source%"^^^|find "-"'^) do ^(
echo echo ^^^<%%date:~0,10%% %%time:~0,8%% 备份记录^^^> 文件最后一次更新时间:%%%%i %%%%j^>^>"%destination%\%name_log%_log.log"
echo ^)
echo start "" "%destination%\%name_log%_log.log"
)>>"%batch_directory%\%name%_backup.cmd"
:add_to_reg
cls
color 1f
title 文件备份器-开机自运行选项
echo.
echo ╭────────╮
echo ╭─────────┤ 开机自运行选项 ├─────────╮
echo │ ╰────────╯ │
echo │ 操作说明: │
echo │ │
echo │ 本操作即将把备份任务加入到开机自运行 │
echo │ │
echo │ 选项中。若要取消开机自运行功能,请在"开始 │
echo │ │
echo │ \运行"中输入"msconfig",打开"系统配置实用 │
echo │ │
echo │ 程序",在"启动"处取消以备份任务名称命名的 │
echo │ │
echo │ 启动项目,或者在注册表[HKEY_LOCAL_MACHINE\ │
echo │ │
echo │ SOFTWARE\Microsoft\Windows\CurrentVersion\ │
echo │ │
echo │ Run]下删除相应的字符串值。 │
echo │ │
echo ╰────────────────────────────╯
echo.
echo 接受请直接敲回车 跳过请按 S
echo ──────────────────────────────
echo.
set choice=
set /p choice= 请输入操作代码(S/回车):
if /i "%choice%"=="s" goto run_at
rem ========在注册表中增添自启动项以便开机时自动备份=============
reg add HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Run /v "%name%" /t REG_SZ /d "%batch_directory%\%name%_backup.cmd" /f >nul 2>nul
:run_at
:: 强制启用计划任务服务
sc config Schedule start= AUTO >nul 2>nul
sc start Schedule>nul 2>nul
rem ==========导入at计划任务=========
for %%i in (%copytime%) do (
at %%i /every:%copydate% "%batch_directory%\%name%_backup.cmd" 2>nul
)
(
echo.&echo.
echo ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
echo.
echo 于%date% %time:~0,8%创建了备份任务
echo 备份对象:"%source%"
echo 备份文件保存位置:"%destination%"
echo 备份程序位置:"%batch_directory%\%name%_backup.cmd"
echo.
echo ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
echo.
echo ________________________________________________________________________________
)>>"%destination%\%name_log%_log.log"
cls
color 1f
title 文件备份器-备份中……
echo.&echo.&echo.&echo.&echo.&echo.
echo ╭────────╮
echo ╭─────────┤ 正在备份文件 ├─────────╮
echo │ ╰────────╯ │
echo │ 操作说明: │
echo │ │
echo │ 备份时间和文件大小、文件数量成正比,请 │
echo │ │
echo │ 耐心等待…… │
echo │ │
echo ╰────────────────────────────╯
xcopy /c /h /i /g /q /r %xcopy_parameter% /x /y "%source%" "%destination%" 2>nul
:: 添加当计划任务出错时提交报告的功能
:: --------------------------------------------------------------------
:: 当使用计划任务让系统自动运行一些命令或程序时,如果运行时发生错误,
:: 在系统的默认设置里,计划任务不会提交错误报告。
:: 此设置就是让计划任务在出现错误时弹出提示信息。
:: 要禁用此功能,请删除注册表中SchedulingAgent下的 NotifyOnTaskMiss
:: 默认不开通;若要开通,请去掉以下reg语句前的注释符号
:: --------------------------------------------------------------------
:: reg add HKLM\SOFTWARE\Microsoft\SchedulingAgent /v NotifyOnTaskMiss /t REG_DWORD /d 00000001 /f >nul 2>nul
cls
title 备份日志
echo.&echo.
type "%destination%\%name_log%_log.log"
echo.&echo.&echo.
echo 按任意键继续...
pause>nul
cls
title 备份任务列表
echo.&echo.&echo.&echo.&echo.&echo.
echo ________________________________________________________________________________
echo.
for %%i in (%copytime%) do (
echo 已经添加了每月^(周^) %copydate% 日 %%i 对"%source%"的备份任务
)
echo.
echo ________________________________________________________________________________
echo.
echo 如要继续添加备份任务,请输入 B ,其他任意键退出...
echo.&echo.
set again=
set /p again= 请选择下一步操作代码:
if /i "%again%"=="b" goto input_source
exit
rem ========删除不再使用的文件或目录=============
:del_unused
:: 以下语句的作用是:如果停止了某项备份任务,则检查硬盘上由本程序生成的cmd文件中,
:: 不在at任务列表中的有哪些;如果有,则删除该cmd,同时删除注册表中对应的字符串值;
:: 如果没有,则不作任何删除操作;
:: 如果由本程序在%ProgramFiles%下创建的目录为空,则删除该目录
for %%i in ("%ProgramFiles%\备份任务程序\*_backup.cmd") do (
at|find /i "%%i">nul || find /i "Code by JM" "%%i">nul && (
del /a /f /q "%%i"
reg delete HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Run /v "%name%" /f >nul 2>nul
)
)
if not exist "%ProgramFiles%\备份任务程序" goto :eof
rd "%ProgramFiles%\备份任务程序" 2>nul
goto :eof
:: ━━━━━━━━━━━━━━━━━以下代码为出错提示━━━━━━━━━━━━━━━━━
:system_error
cls
color 0c
title 文件备份器-操作系统不支持
echo.&echo.&echo.&echo.&echo.&echo.
echo ╭────────╮
echo ╭─────────┤ 操作系统不支持 ├─────────╮
echo │ ╰────────╯ │
echo │ │
echo │ │
echo │ 非常抱歉,该程序只能在XP环境下运行 │
echo │ │
echo │ 程序即将退出... │
echo │ │
echo ╰────────────────────────────╯
ping -n 4 127.1>nul && goto :eof
:popedom_error
cls
color 0c
title 文件备份器-权限不足
echo.&echo.&echo.&echo.&echo.&echo.
echo ╭────────╮
echo ╭─────────┤ 权限不足 ├─────────╮
echo │ ╰────────╯ │
echo │ │
echo │ │
echo │ │
echo │ 非常抱歉,当前用户权限太低,无法运行本程序 │
echo │ │
echo │ 请换用具备管理员组权限的其他用户帐号来运行 │
echo │ │
echo │ 按任意键退出... │
echo │ │
echo ╰────────────────────────────╯
pause>nul
goto :eof
:subarea_noexist
cls
color 0c
title 文件备份器-磁盘 "%subarea%" 不存在
echo.&echo.&echo.&echo.&echo.
echo ╭────────╮
echo ╭─────────┤ 磁盘分区不存在 ├─────────╮
echo │ ╰────────╯ │
echo │ │
echo │ │
echo │ 盘符为 %subarea% 的磁盘分区不存在 │
echo │ │
echo │ 按任意键返回上一步重新选择路径 │
echo │ │
echo ╰────────────────────────────╯
echo.
pause>nul
goto input_destination
:source_noexist
cls
color 0c
title 文件备份器-文件不存在
echo.&echo.&echo.&echo.&echo.
echo ╭────────╮
echo ╭─────────┤ 文件不存在 ├─────────╮
echo │ ╰────────╯ │
echo │ │
echo │ │
echo │ 要备份的文件不存在 │
echo │ │
echo │ 按任意键返回上一步重新选择 │
echo │ │
echo ╰────────────────────────────╯
echo.
pause>nul
goto input_source
:forbid_to_backup
cls
color 0c
title 文件备份器-禁止备份
echo.&echo.&echo.&echo.&echo.
echo ╭────────╮
echo ╭─────────┤ 禁止备份 ├─────────╮
echo │ ╰────────╯ │
echo │ │
echo │ │
echo │ 本程序不支持全盘备份 │
echo │ │
echo │ 按任意键返回上一步重新选择 │
echo │ │
echo ╰────────────────────────────╯
echo.
pause>nul
goto input_source
:forbid_to_build_1
cls
color 0c
title 文件备份器-禁止创建
echo.&echo.&echo.&echo.&echo.
echo ╭────────╮
echo ╭─────────┤ 禁止创建 ├─────────╮
echo │ ╰────────╯ │
echo │ │
echo │ │
echo │ 为了数据的安全,请勿直接备份到根目录下 │
echo │ │
echo │ 按任意键返回上一步重新选择 │
echo │ │
echo ╰────────────────────────────╯
echo.
pause>nul
goto input_destination
:forbid_to_build_2
cls
color 0c
title 文件备份器-禁止创建
echo.&echo.&echo.&echo.&echo.
echo ╭────────╮
echo ╭─────────┤ 禁止创建 ├─────────╮
echo │ ╰────────╯ │
echo │ │
echo │ 警告:保存位置与要备份文件的位置路径相同 │
echo │ │
echo │ 或者位于要备份文件的某一目录下 │
echo │ │
echo │ 为了数据的安全,请重新选择保存位置 │
echo │ │
echo │ 按任意键返回上一步重新选择 │
echo │ │
echo ╰────────────────────────────╯
echo.
pause>nul
goto input_destination
:destination_input_erro
cls
color 0c
title 文件备份器-路径输入错误
echo.&echo.&echo.&echo.&echo.
echo ╭────────╮
echo ╭─────────┤ 路径输入错误 ├─────────╮
echo │ ╰────────╯ │
echo │ │
echo │ │
echo │ 您的路径输入有错误 │
echo │ │
echo │ 请在半角状态输入冒号和反斜杠 │
echo │ │
echo │ 按任意键返回上一步重新选择 │
echo │ │
echo ╰────────────────────────────╯
echo.
pause>nul
goto input_destination
:date_error
cls
color 0c
title 文件备份器-日期输入错误
echo.&echo.
echo ╭────────╮
echo ╭─────────┤ 日期输入错误 ├─────────╮
echo │ ╰────────╯ │
echo │ │
echo │ 您的日期输入有错误 │
echo │ │
echo │ │
echo │ 1. 日期不能字母和数字混用; │
echo │ │
echo │ 2. 单个的数字式日期不能大于31; │
echo │ │
echo │ 3. 字母式的日期只能是 M,T,W,Th,F,S,Su 中的 │
echo │ │
echo │ 任意几个,不区分大小写; │
echo │ │
echo │ 4. 日期之间只能用逗号分隔。 │
echo │ │
echo │ │
echo │ 按任意键返回上一步重新选择 │
echo │ │
echo ╰────────────────────────────╯
pause>nul
goto input_date
:time_error
cls
color 0c
title 文件备份器-时间输入错误
echo.&echo.&echo.&echo.&echo.
echo ╭────────╮
echo ╭─────────┤ 时间输入错误 ├─────────╮
echo │ ╰────────╯ │
echo │ │
echo │ │
echo │ 您的时间输入有错误 │
echo │ │
echo │小时数不能大于23,分钟数不能大于59,每个时间点用空格分隔│
echo │ │
echo │ 按任意键返回上一步重新选择 │
echo │ │
echo ╰────────────────────────────╯
echo.
pause>nul
goto input_time
:name_exist
cls
color 0c
title 文件备份器-同名程序 "%name%_backup.cmd" 已经存在
echo.&echo.&echo.&echo.&echo.
echo ╭────────╮
echo ╭─────────┤ 存在同名程序 ├─────────╮
echo │ ╰────────╯ │
echo │ │
echo │ │
echo │ "%ProgramFiles%\备份任务程序"下已存在同名的批处理程序│
echo │ │
echo │ 按任意键返回上一步重新选择 │
echo │ │
echo ╰────────────────────────────╯
echo.
pause>nul
goto input_name
:: ━━━━━━━━━━━━━━━━━以下代码为被调用的子过程━━━━━━━━━━━━━━━━━
rem ========查看保存位置下的内容以决定 追加/覆盖/重新选择 等操作========
:view_directory
explorer "%destination%"
goto :eof
rem ========简化每天都需要备份时的操作========
:all_date
set copydate=1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31
goto input_time
goto :eof
rem ========查看备份脚本程序========
:view_batch
explorer "%ProgramFiles%\备份任务程序"
goto input_source
goto :eof
rem ========显示备份清单========
:list
cls
color 1f
title 文件备份器-备份清单
echo.
echo ________________________________________________________________________________
echo.
echo 备份任务名称:"%name%"
echo.
echo 要备份的文件:"%source%"
echo.
echo 保存位置:"%destination%"
echo.
echo 备份日期: %copydate%
echo.
echo 备份时间:%copytime%
echo.
echo ________________________________________________________________________________
echo.
goto :eof
rem ========日志里的更新列表头========
:build_head
(
echo :head
echo set times=1
echo ^(
echo echo _____________________________________________________________________________________
echo echo.
echo echo *更新列表^^^(%%date:~0,10%% %%time:~0,8%%^^^):
echo echo.
echo ^)^>^>"%destination%\%name_log%_log.log"
echo goto :eof
)>>"%batch_directory%\%name%_backup.cmd"
goto :eof 更新历史:
更新历史:
07.4.7~8
搁置了将近半年之久,再次更新代码。此次更新动作较大,主要做了以下改动:
① 考虑到恢复原始文件属性的操作有很大风险(比如丢失了属性配置batch
文件会导致无法恢复文件的原始属性,从而给文件读写带来无尽的麻烦),因此,
取消了对备份后文件加上"系统+只读"属性的操作;相应地,一并取消了恢复备份
的脚本程序,使得备份效率大为提升;
② 修改了不能正确删除注册表中相关项目的bug;
③ 优化了日期及时间的输入检测功能,备份速度有所提高;
④ 全面精简了代码;
⑤ 把更新历史从代码中分离出来,减少了cmd文件的体积。
此为V2.4;若功能方面没有什么大的bug,将作为final版推出,不再更新。
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的提醒),但需要注册表中的特定键
值为默认设置(有关讨论请参考http://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_MACHINE\Software\Microsoft\Windows\
CurrentVersion\Run) 增添了开机自动运行备份程序的键值( 以备份任务名称作
为键值) ,尽可能减少错过备份的情况;如果更新了内容,则备份完毕后自动打
开备份日志;修正了几处错误;此为V1.7;
06.5.30
完善了备份流程,在列出创建备份任务的清单时,可更改备份任务内容;在
创建备份任务的同时,强制启动计划任务服务,并立即作复制操作;显示各磁盘
分区剩余空间情况的时候,增加了显示磁盘卷标名的功能;更改了注意事项界面
中的前景色和背景色,使色调显得明快而柔和;
06.5.28
增加了在每周的指定日期进行备份的功能;添加了当计划任务出错时提交报
告的功能;完善了日志记录功能,只有当文件更新时才会改写日志;完善了注意
事项中的内容;增加了删除所有计划任务的功能;此为 V1.6 ;
06.5.26
增加了不允许把保存路径设置为与源文件路径相同、或者为源文件某一目录
的功能;添加了注意事项提示功能;修正了几处错误;部分代码参照中国DOS 联
盟论坛(http://www.cn-dos.net/forum) 网友bagpipe所发帖子,使一些代码得
到精简;此为V1.5;
06.5.25
增加了把备份文件的保存目录拖曳到窗口执行的功能;增加了批量停止指定
备份任务的功能;修改了几处错误;精简了部分代码;此为V1.4;
06.5.24
增加了把要备份的文件拖曳到窗口执行的功能;感谢中国DOS 联盟论坛
(http://www.cn-dos.net/forum)版主willsort提供代码;此为V1.3;
06.5.23
修正了一处关键错误,使得备份能顺利进行下去;在中国DOS 联盟论坛
(http://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; 注:
1.因为还没找到显示比例为4:3的电脑显示器,只能将就我的显示比例了(分辨率为1280×768);
2.自动完成文件名这一功能非常实用,但尚有不完善之处,详情请看46楼,请各位高手帮忙解决;
3.当xcopy加上/e参数时,复制文件的时候会把文件所在目录下的文件夹(不包含其中的文件)都复制过去;当备份的是文件夹且结构为"文件夹1-文件夹2-文件夹3-文件"的时候,会去掉最上层的文件夹;百思不得其解;
4.更新之处请看更新历史;
5.[求助]有没有谁装了2K的系统,如果有的话,请帮忙测试一下在2K下能不能通过(要把:check_system这一节代码去掉),有测试过的请帮忙回帖反馈一下。目前我只知道在显示%date%和%time%的时候会不一样;
6.如果有什么地方需要完善的,欢迎跟帖;
有关本程序的讨论主要有:
[1]什么情况下该使用变量延迟?
http://www.cn-dos.net/forum/viewthread.php?tid=20733
[2]监视文件操作的批处理该如何编写?
http://www.cn-dos.net/forum/viewthread.php?tid=20732
[3]如何用固定长度显示长度不一致的字符?
http://www.cn-dos.net/forum/viewthread.php?tid=20734
[4]怎样去掉DOS窗口的下拉条
http://www.cn-dos.net/forum/viewthread.php?tid=20040
[5]at命令中为什么无法显示%username%
http://www.cn-dos.net/forum/viewthread.php?tid=20238
[6][部分已结]如何显示磁盘的剩余空间?
http://www.cn-dos.net/forum/viewthread.php?tid=19738
[7]长文件名如何应用于批处理文件中
http://www.cn-dos.net/forum/viewthread.php?tid=19223
[8][求助]在2K环境下date命令的运行结果
http://www.cn-dos.net/forum/viewthread.php?tid=20043
[9]如何检测文件名带空格的文件夹是否存在
http://www.cn-dos.net/forum/viewthread.php?tid=19836
[10]怎样复制指定内容到指定文件里去
http://www.cn-dos.net/forum/viewthread.php?tid=19855
[11][已结]dir命令查询目录找不到文件是什么原因
http://www.cn-dos.net/forum/viewthread.php?tid=19803
[ Last edited by namejm on 2007-4-8 at 11:18 AM ]
附件
1: 文件备份器(Final).rar (2007-4-9 00:20, 117.32 K,下载次数: 328)
|
|
2006-5-22 23:35 |
|
|
willsort
元老会员
Batchinger
积分 4432
发帖 1512
注册 2002-10-18
状态 离线
|
『第
2 楼』:
Re namejm:
很不错的一个批处理脚本,可以看出兄十分用心。因此我有一个建议,将此主题改造为关于“文件自动备份批处理脚本”的原创主题,首帖转贴最新的源码,回复帖对其中涉及的若干细节和问题进行讨论。这要求转移和合并你过去发表的一些主题帖,因此需要征得你的同意。
关于at3命令的执行问题,因为代码尚没有看完,因此无法发表什么意见,仅推测似与其所对应的备份脚本有关,因此需要贴出这段批处理的代码。
另外,仅就以下引用自源码中的一节略作讨论:
Quote: | set /p source= 请输入要备份文件的路径:
:: 这里可以提示直接将备份目标拖拽入运行窗口中,即可获得源路径
for /f "delims=:\" %%i in ("%source%") do set subarea1=%%i
:: 似乎是获取源的盘符,为何不使用 set subarea1=%source:~0,1%
if not "%source%"=="" set source=%source%
:: 此句意义未明,尚请指教
:: 如果是将路径格式化,需要使用for %%p in ("%source%") do set source=%%~fp
if "%source%"=="" goto input_source
:: 建议将直接按下回车的选择(即%source%为空)分配给使用频率高的操作
if "%source%"=="0" exit
if "%source%"=="1" goto backup_task
echo "%source%"|find "%subarea1%:\" > nul
if "%ERRORLEVEL%"=="1" goto input_source
:: 判断路径中是否含有盘符?可否用 if "%source:~1,2%"==":\"
if "%source%"=="%subarea1%:\" goto forbid
:: 判断路径是否为根路径?当 source 为 C:\\ 或者 C:\. 时将不起作用
if not exist "%source%" goto source_noexist
goto input_object
:: object 的含义为对象,与备份目标有歧义,不如改为target或destination |
|
[ Last edited by willsort on 2006-5-23 at 01:48 ]
|
※ Batchinger 致 Bat Fans:请访问 [讨论]批处理编程的异类 ,欢迎交流与共享批处理编程心得! |
|
2006-5-23 01:47 |
|
|
bagpipe
银牌会员
DOS联盟捡破烂的
积分 1144
发帖 425
注册 2005-10-20 来自 北京
状态 离线
|
『第
3 楼』:
LZ真是有耐心,这么长,比我毕业论文都长,佩服,佩服..........正如WILLSOFT所说代码没有看完呢还得慢慢消化一下才可以的............
|
|
2006-5-23 12:30 |
|
|
Climbing
铂金会员
网络独行侠
积分 6962
发帖 2753
注册 2003-4-16 来自 河北保定
状态 离线
|
『第
4 楼』:
我觉得at出现的错误跟批处理没有太大的关系,有可能是有其它方面的原因。
从楼主的批处理来看,只要有一个at计划正常运行了,那么其它的也应该没有问题。
对楼主的耐心表示敬意,不过,如果你仅仅是为了实现文件备份功能而写这个批处理,实在不如引进一些第三方工具来得简单,例如:SecondCopy,或者同步软件CmdSync等 。当然,个人的环境不同,所以方法也不同,我的仅仅是建议。
|
偶只喜欢回答那些标题和描述都很清晰的帖子!
如想解决问题,请认真学习“这个帖子”和“这个帖子”并努力遵守,如果可能,请告诉更多的人!
|
|
2006-5-23 13:05 |
|
|
doscc
中级用户
积分 256
发帖 93
注册 2006-3-26 来自 广东
状态 离线
|
『第
5 楼』:
同意4楼的建议!
对楼主的耐心表示敬意
虽然脚本可以帮我们完成一些 大量重复的工作!
但是有时用一些第三方软件也不错的.
|
|
2006-5-23 14:11 |
|
|
namejm
荣誉版主
batch fan
积分 5226
发帖 1737
注册 2006-3-10 来自 成都
状态 离线
|
『第
6 楼』:
to willsort 版主:
我不清楚你进行"转移和合并你过去发表的一些主题帖"这个操作的时候需要什么条件,我十分高兴这个脚本能得到大家的进一步完善,请版主按照你的想法编辑就是了,有什么地方需要我做的,我尽量配合.谢谢willsort.
报告一下问题所在:
刚才突然回想起手动执行生成的计划任务批处理,屏幕显示"……是否改写?(YES or NO or All)"(大意如此,现在时间匆忙,没来得及细看),看来是因为at是后台运行的,对需要手动确认的命令不会作任何提示,所以造成了cmd.exe和xcopy.exe进程一直存在,而备份操作没有执行的现象.
现在在xcopy一句后加上 /y 参数,问题解决.
各位的回复都看了一下,看来这个脚本还有很多需要完善的细节.因为马上要上班去了,没时间一一回复,只有等下了班再来回答,请各位原谅.同时,也请大家继续挑里面的毛病,特别是看有有些地方没有什么更好的解决办法.在此谢过各位.
|
|
2006-5-23 14:18 |
|
|
namejm
荣誉版主
batch fan
积分 5226
发帖 1737
注册 2006-3-10 来自 成都
状态 离线
|
『第
7 楼』:
感谢willsort版主的点评,以下是我的一些想法:
"set /p source= 请输入要备份文件的路径:
:: 这里可以提示直接将备份目标拖拽入运行窗口中,即可获得源路径"
——居然还可以直接拖过去就能显示路径,呵呵,意外收获,在此谢过willsort。如果路径带有空格,直接拖过去的话,会自动在路径首尾添加引号,而当初为了照顾手工输入带空格的路径,下面的变量引用都是加了引号的,如果提示用拖曳的办法的话,会造成程序出错。如果不允许手工输入只允许拖曳的话,再去掉变量引用的引号,应该可以解决这个矛盾。暂时还不好取舍。
"for /f "delims=:\" %%i in ("%source%") do set subarea1=%%i
:: 似乎是获取源的盘符,为何不使用 set subarea1=%source:~0,1%"
——如果用拖曳的方法输入的路径带空格的话,只能取到前引号。如果采用上一条的方案,只允许拖曳的话,会导致错误,看来拖曳的方法挺容易出错的。
"if not "%source%"=="" set source=%source%
:: 此句意义未明,尚请指教
:: 如果是将路径格式化,需要使用for %%p in ("%source%") do set source=%%~fp"
——说实话,这句我也不太弄得明白,是我从深山红叶光盘的批处理程序中抄袭过来的,当时以为是获取键盘输入的一种格式,没有细想。
"if "%source%"=="" goto input_source
:: 建议将直接按下回车的选择(即%source%为空)分配给使用频率高的操作
if "%source%"=="0" exit
if "%source%"=="1" goto backup_task"
——我的本意是检测是否有输入内容,如果没有的话,则强制输入,不允许跳过,感觉这样处理比较好,暂时不打算更改此处代码。
"echo "%source%"|find "%subarea1%:\" > nul
if "%ERRORLEVEL%"=="1" goto input_source
:: 判断路径中是否含有盘符?可否用 if "%source:~1,2%"==":\" "
——同上面的道理,在拖曳输入的时候,只能取到前引号。
"if "%source%"=="%subarea1%:\" goto forbid
:: 判断路径是否为根路径?当 source 为 C:\\ 或者 C:\. 时将不起作用"
——当时没有考虑到这种情况,多谢版主提醒,现在在后面增加两行代码,应该可以避免这个错误:
if "%source%"=="%subarea1%:\\" goto forbid
if "%source%"=="%subarea1%:\." goto forbid
"if not exist "%source%" goto source_noexist
goto input_object
:: object 的含义为对象,与备份目标有歧义,不如改为target或destination"
——说起来惭愧,对E文我一向比较头疼,所以经常会闹笑话。在新的代码里已经改过来了。多谢指正。
以下是修改过的代码:
[ Last edited by willsort on 2006-5-24 at 01:42 ]
|
|
2006-5-23 18:40 |
|
|
namejm
荣誉版主
batch fan
积分 5226
发帖 1737
注册 2006-3-10 来自 成都
状态 离线
|
『第
8 楼』:
Quote: | Originally posted by Climbing at 2006-5-23 13:05:
对楼主的耐心表示敬意,不过,如果你仅仅是为了实现文件备份功能而写这个批处理,实在不如引进一些第三方工具来得简单,例如:SecondCopy,或者同步软件CmdSync等 。当然,个人的环境不同,所以方法也不同,我的仅仅是建议。 |
|
多谢老兄提供了这两个程序的线索,网上搜索了一下,它们的功能令人怦然心动。
但是有两个缺陷:1.正如我在这个脚本程序的更新历史里所说的那样,“网上的备份软件有诸多限制”,SecondCopy有30天免费使用期的限制,像我等不会破解之道的菜鸟,拿来使用30天之后,可能又得把系统时间往前调N天(还不一定有效),或者再手工备份,而网上的注册码都是过了期的,破解的似乎也没有;2.都是E文的。这个一直是令我很头疼的事情。虽然知道不多懂点E文在网络里不好混,在现实生活中也混不好,但是自己专业的限制,大学毕业之后就没多少心思再在E文上下工夫,所以我用的软件要么是国人开发的,要么就是汉化过的,可怜:(
综合以上原因,我决定还是自己编一个脚本程序,一来可以练技术,二来也可以拿来给我那些比我更菜的朋友们用。苦笑ing……
|
|
2006-5-23 18:54 |
|
|
willsort
元老会员
Batchinger
积分 4432
发帖 1512
注册 2002-10-18
状态 离线
|
『第
9 楼』:
Re namejm:
我已经将主题首帖作了一些改动,包括标题的修改和正文内容顺序的调整。
原来试图将所有兄所发的与本程序有关的讨论主题合并到这里来,却发现兄对这个脚本下了不少功夫,竟然发现了十数个主题与此相关,如此一来,合并工作量大不说,也会导致许多原来相关性不大的讨论主题夹杂在同一主题中,反而降低了主题的作用。因此,最终决定只在首帖中给出所有相关讨论主题的链接以供查阅索引。
其次,将兄7楼中的代码转移到首帖中,这是考虑到以下原因:一是因为代码体积过大,如果出现多个差异不大的版本,将会降低页面的打开速度、增加用户的阅读时间,同时耗费更多的论坛空间和时间资源;二是因为我们发表程序的原则是尽可能让用户以最方便的方式获取最新的版本,而如果将新版本更新在回复帖中,可能需要滚动甚至翻页才能得到,那就抬高了推广的门槛。因此,建议兄发布新版程序时,也能将代码编辑到首帖中。
再次,关于我引用的那一小节,你的两难是可以解决的。用户可以拖拽备份源,也可以直接输入源路径(绝对路径或者相对路径),无论它是否含有引号,无论它是否含有非标准的路径引用方式(C:\\,C:\.\),我们都可以通过对路径串进行预先的格式标准化处理来解决这些不兼容的问题。以下的语句可以剔除路径中可能存在的引号,将相对路径转换为绝对路径,将非标准路径转换为标准路径(C:\\-->C:\),并判断路径是否有效地存在,是否是根路径。 不过它仍无法抵抗路径中出现的非法字符(>|),不知其他兄弟还有什么更好的办法没有?
最后,不知兄使用何种环境编写代码?但从注释的宽度达到114来看,兄或许使用的是宽屏显示器,所以不虞注释的换行浏览问题。然而根据论坛和我的系统环境(17"+XP+EditPlus2)中贴出的代码来看,无论是否开启自动换行功能,注释的宽度过大都影响了代码的可阅读性。
set _src=
for %%p in ("%source%") do if exist %%p set _src=%%~fp
if "%_src%"=="" for %%p in (%source%) do if exist %%p set _src=%%~fp
if "%_src:~1,2%"==":\" goto forbid
set source=%_src% [ Last edited by willsort on 2006-5-24 at 02:54 ]
|
※ Batchinger 致 Bat Fans:请访问 [讨论]批处理编程的异类 ,欢迎交流与共享批处理编程心得! |
|
2006-5-24 02:47 |
|
|
namejm
荣誉版主
batch fan
积分 5226
发帖 1737
注册 2006-3-10 来自 成都
状态 离线
|
『第
10 楼』:
Quote: | Originally posted by willsort at 2006-5-24 02:47:
Re namejm:
最后,不知兄使用何种环境编写代码?但从注释的宽度达到114来看,兄或许使用的是宽屏显示器,所以不虞注释的换行浏览问题。然而根据论坛和我的系统环境(17"+XP+EditPlus2)中贴出的代码来看,无论是否开启自动换行功能,注释的宽度过大都影响了代码的可阅读性。 |
|
老大果然一眼看出问题的所在,我用的正是宽屏电脑,14''+XP,分辨率为1280×768,以前在学做网页的时候就因为宽屏的原因与标准的4:3屏幕不一致而痛苦不堪,现在居然把这个细节给搞忘记了,真是一语惊醒梦中人,看来得找个4:3的显示器来修改.
最初不是为了编这个脚本才发的帖子,而是因为在做光盘的时候,要从光盘中提取指定的E书到电脑上.随着兴趣的越发浓厚,而对批处理的热情一发不可收拾,在自己的电脑上捣鼓了不少脚本来增强系统的功能,自我娱乐.刚下班回来,还有点头昏脑胀,先睡个午觉,晚上下班回来再回复,请各位原谅.
|
|
2006-5-24 12:48 |
|
|
namejm
荣誉版主
batch fan
积分 5226
发帖 1737
注册 2006-3-10 来自 成都
状态 离线
|
『第
11 楼』:
Quote: | Originally posted by willsort at 2006-5-24 02:47:
Re namejm:
再次,关于我引用的那一小节,你的两难是可以解决的。用户可以拖拽备份源,也可以直接输入源路径(绝对路径或者相对路径),无论它是否含有引号,无论它是否含有非标准的路径引用方式(C:\\,C:\.\),我们都可以通过对路径串进行预先的格式标准化处理来解决这些不兼容的问题。以下的语句可以剔除路径中可能存在的引号,将相对路径转换为绝对路径,将非标准路径转换为标准路径(C:\\-->C:\),并判断路径是否有效地存在,是否是根路径。 不过它仍无法抵抗路径中出现的非法字符(>|),不知其他兄弟还有什么更好的办法没有? |
|
能不能把路径用for来解析,如果有非法符号就跳转到警告界面?
|
|
2006-5-24 17:32 |
|
|
namejm
荣誉版主
batch fan
积分 5226
发帖 1737
注册 2006-3-10 来自 成都
状态 离线
|
『第
12 楼』:
Quote: | Originally posted by willsort at 2006-5-24 02:47:
Re namejm:
set _src=
for %%p in ("%source%") do if exist %%p set _src=%%~fp
if "%_src%"=="" for %%p in (%source%) do if exist %%p set _src=%%~fp
if "%_src:~1,2%"==":\" goto forbid
set source=%_src% |
|
把上面这段代码压缩成一句插入,测试了一下,觉得没什么问题,已经更新到脚本里去了,更新位置如下:
set source=
set /p source= 请输入要备份文件的路径:
for %%p in (%source%) do set source=%%~fp
for /f "delims=:\" %%i in ("%source%") do set subarea1=%%i 发现个问题,看来还得改动输入提示
title 请输入源文件路径
echo ╭────────╮
echo ╭─────────┤选择要备份的文件├─────────╮
echo │ ╰────────╯ │
echo │ 操作说明: │
echo │ │
echo │ 本程序能把指定文件在指定时间内备份 │
echo │ │
echo │ 到指定位置。请把要备份的文件拖曳至本窗 │
echo │ │
echo │ 口(推荐做法),或者手工输入需要备份文件 │
echo │ │
echo │ 的完整路径(带空格的路径需在首尾加半角 │
echo │ │
echo │ 状态下的双引号;请勿输入非法字符;否则 │
echo │ │
echo │ 会产生无法预料的错误),然后回车确认。 │
echo │ │
echo ╰────────────────────────────╯
echo.
echo 查看已存在的备份任务请按 1 退出请按 0
echo ────────────────────────────── ([code]与[code]之间的内容无法再应用字符颜色设置,不能醒目地标注出来,挺遗憾的)
[ Last edited by namejm on 2006-5-25 at 13:28 ]
|
|
2006-5-24 23:54 |
|
|
willsort
元老会员
Batchinger
积分 4432
发帖 1512
注册 2002-10-18
状态 离线
|
『第
13 楼』:
Re namejm:
问题的关键在于我们不能确定路径串的前后是否存在引号,所以不能贸然决定是否使用引号包含路径串,所以无法约束其中的非法字符。这我曾在[1]中作过类似的讨论,目前没有很好的解决办法。
而任何对路径串进行探测和分析的语句(无论echoif、for),都要求命令行中出现路径串本身,而如果未受约束的非法字符显然会破坏命令行的正常秩序。甚至可能不会出现语法错误的提示,而意外地产生一些垃圾文件。
在你现在的代码中,如果某些用户为了安全起见而将含空格路径用引号引起,那么代码显然会语法错误而中止。而目前为止,我们测试的仍只是善意用户的合法行为,还没有真正进行一些非善意的极限边界测试。
所以说,要编制一个“健壮性”很强的代码是很困难的,尤其是在自由灵活的批处理中。
[1][讨论]批处理编程的异类: if语句中防空字符的选择
http://www.cn-dos.net/forum/viewthread.php?tid=12388#pid100419
|
※ Batchinger 致 Bat Fans:请访问 [讨论]批处理编程的异类 ,欢迎交流与共享批处理编程心得! |
|
2006-5-25 00:12 |
|
|
namejm
荣誉版主
batch fan
积分 5226
发帖 1737
注册 2006-3-10 来自 成都
状态 离线
|
『第
14 楼』:
Quote: | Originally posted by willsort at 2006-5-24 02:47:
Re namejm:
以下的语句可以剔除路径中可能存在的引号,将相对路径转换为绝对路径,将非标准路径转换为标准路径(C:\\-->C:\),并判断路径是否有效地存在,是否是根路径。 |
|
set _src=
for %%p in ("%source%") do if exist %%p set _src=%%~fp
if "%_src%"=="" for %%p in (%source%) do if exist %%p set _src=%%~fp
if "%_src:~1,2%"==":\" goto forbid
set source=%_src%
以上的代码我插入到
set source=
set /p source= 请输入要备份文件的路径:
与
if not "%source%"=="" set source=%source%
if "%source%"=="" goto input_source
if "%source%"=="0" exit
if "%source%"=="1" goto backup_task
之间,并不能剔除带空格路径中的前后引号,而是跳转到禁止全盘复制的界面,难道是我插入的位置错了吗?
[ Last edited by namejm on 2006-5-25 at 22:38 ]
|
|
2006-5-25 18:32 |
|
|
willsort
元老会员
Batchinger
积分 4432
发帖 1512
注册 2002-10-18
状态 离线
|
『第
15 楼』:
Re namejm:
很抱歉!问题出在if "%_src:~1,2%"==":\" goto forbid句上,这句代码是我在完成路径测试后,转贴前临时插入进去的,因未经测试而导致出错!将它改为if "%_src:~1,3%"==":\" goto forbid可以解决问题。
但以上代码还无法完善解决不存在文件及文件夹路径串的问题,将代码[1]替换为代码[2]可以解决这个问题。当然,新代码仍然无法防御“<|>”这些非法字符。
[1]Old code
set /p source= 请输入要备份文件的路径:
for %%p in (%source%) do set source=%%~fp
for /f "delims=:\" %%i in ("%source%") do set subarea1=%%i
if not "%source%"=="" set source=%source%
if "%source%"=="" goto input_source
if "%source%"=="0" exit
if "%source%"=="1" goto backup_task
echo "%source%"|find "%subarea1%:\" > nul
if "%ERRORLEVEL%"=="1" goto input_source
if "%source%"=="%subarea1%:\" goto forbid
if "%source%"=="%subarea1%:\\" goto forbid
if "%source%"=="%subarea1%:\." goto forbid
if not exist "%source%" goto source_noexist
goto input_destination [2]New code
set _i=
set source=
set /p source= 请输入要备份文件的路径:
for %%s in (%source%) do set /a _i+=1
if "%_i%"=="1" for %%p in (%source%) do set source=%%~p
:: 以上两句为判断%source%中是否存在引号,有则剔除
if "%source%"=="" goto input_source
if "%source%"=="0" goto :eof
if "%source%"=="1" goto backup_task
if not exist "%source%" goto source_noexist
for %%p in ("%source%") do if "%%~fp"=="%%~dp\" goto forbid
goto input_destination
|
※ Batchinger 致 Bat Fans:请访问 [讨论]批处理编程的异类 ,欢迎交流与共享批处理编程心得! |
|
2006-5-25 22:30 |
|
|