windows“运行”自定义“命令”的实现


(版权所有,转载请注明)

Gavin Chou

2011-11


摘 要:本文介绍了通过分析windows快捷方式扫描目录以及使用脚本语言结合批处理命令创建快捷方式的方法达到在“开始”菜单“运行”选项里输入自定义 “命令”实现通过输入命令的方式打开/运行任文件(程序、文件及文件夹)。使用此种方法能够最大化缩短寻找程序、文件的时间,从而大大提高使用电脑学习、 工作的效率。

关键词:Windows;注册表;运行;快捷方式;系统目录;BAT;VBS;命令

An Implementation of Custom “command” in Windows’ “Run” dialog

Gavin Chou

Abstract: (This paper is not formal, the abstract in English is omitted)

Keywords: Windows; registry; Run; Shortcut; system-root-directory; BAT; VBS; Command


1  引言
如果对本文过程不感兴趣,可以直接跳到第4章(结论)。

本 文是作者对自己于2009年写的一个程序(应该叫脚本更加合适)的一个总结,涉及到了Windows的注册表、快捷方式、VBS脚本语言、批处理命令等内 容,也提到了使用Windows功能的一些小技巧,在此和大家分享。本文面向的读者为:1、对Windows有兴趣的;2、对Windows系统结构有一 定了解的;3、对BAT或VBS感兴趣的; 

Windows出来已经有一些年头了,自从有了Windows后人们就能够通过操作鼠标很方 便地完成大量的操作,不必再像DOS时代每个操作都需要用键盘敲命令来实现。但是,随着操作系统的不断升级,系统变得越来越聪明,越来越多的操作依赖于鼠 标来实现,操作者对系统现成的功能也越来越依赖,操作虽然方便了,但是操作的效率是否就非常高了呢?作者认为并不是这样的,很多时候键盘的操作效率比鼠标 要高的多(打DOTA就是一个很好的例子,如果使用鼠标来施放技能,那么估计就被杀成鬼了……)。写过程序的人都知道,一个东西封装程度越高,那么它使用 起来就越方便,但是同时它的限制就多了,灵活性也就越差,矛盾总是存在的,操作系统(某些方面)也一样。举个例子,有人在使用电脑做工程/项目时,需要使 用很多软件,参考很多资料,那么就需要不断打开很多窗口,窗口多时还要关闭一些窗口,假设这些东西都能够在桌面(当然是Windows的桌面)找到,那么 要打开一个文档或程序就要返回桌面一次,寻找->打开,如果资料还不都在桌面上,那么还要深入到某个目录下寻找……这些操作可以通过操作鼠标和键盘 组合来实现,但大都是重复而浪费时间,这些重复而浪费时间的事应该让不会思考的电脑完成,我们需要做的事就是告诉电脑我们想做什么---输入命令,然后我 们就能打开想打开的东西,就像输入“记事本”,电脑就打开一个记事本;输入“工具”,电脑就打开我们常用工具所在的文件夹;输入“给我放首歌”,电脑就播 放一首歌(放首什么歌呢?把歌名作为参数就可以了。说到这个,顺便给读者讲个笑话:一个好程序员是不会写一个“摧毁地球”的函数的,他只会写一个“摧毁行 星”的函数,而把地球作为它的参数……),命令是自定义的,就不需要为记住命令而花不必要的时间,重复操作的时间就省下来了。
摘要所描述的可能有 些抽象,不过也总结了本文想要介绍的内容。可能对于对window了解不是很深入的读者还是不太清楚摘要中所描述的功能,那么接下来作者再举个例子吧。很 多人都看过《钢铁侠》这部电影,电影里有一幕给作者的印象特别深刻,那就是Stark的助理在公司办公室的电脑上看到了Stark被匪徒绑架后要挟公司高 层的录像,助理不知道匪徒说的是哪国语言,于是调出来个小对话框,输入“Translate”(不包括引号……),匪徒说的鸟语就变成了英语。作者在摘要 里描述的功能就是类似Stark的助理输入“Translate”的功能,当然,《钢铁侠》是个科幻电影,所以本文所要阐述的功能并没有电影里的那么强 大,只是类似(但是,相信在未来10年内就能实现了,而且还是可以是声控的!),就向电影里的一样,能够让电脑(Windows)的操作者省去找来翻译软 件这种繁琐而浪费时间的动作。当然,初期设置是必须的,本文从第2章开始就会提到如何实现。

本文所描述的功能均在Windows XP 下实现,其他版本的Windows用户可以参考借鉴,文中也会提到应付不同版本Windows的方法。


2  功能的实现
2.1  开始->运行功能的引入
会使用“开始->运行”的可以直接跳到2.2节。

首先,让我们来做几个实验:1、单击开始菜单里的 “运行”项(这就是我们通常所说的“开始->运行”,在Windows7下开始菜单的那个搜索输入框也有同样的效果,按住Windows徽标的同时再按“R”键也能够调出“运行”对话框,Windows徽标和R键是作者用得最多的按键),


输 入“notepad”(不包括引号),回车,如果不出意外的话读者应该会打开了一个记事本的窗口,要用记事本来做什么事情,读者自己决定。2、同样在运行 的小对话框里输入“winword”,如果读者的电脑安装有office套件的话,那么(从名字就能看出来)应该就能打开我们常用的word了……除此之 外还有很多我们能够打开的东西,包括一些系统工具,在运行对话框里输入:CMD.EXE(命令行),control(控制面板),explorer(我的 文档)等等(标准系统的工具,这些工具的使用也是大有学问,但不是本文主要内容,如果有时间的话,作者再进行一些使用经验的总结)。但是,有读者可能会去 尝试输入“powerpoint”了,当然得到的结果就是
 


这又是为什么呢?既然word可以,excel可以,为什么powepoint就不行呢?在下一节中读者就可以得到答案。


2.2  “运行”对话框的浅析

经 过作者的不断摸索和总结,对“运行”对话框有了一定的了解。“运行”对话框里输入的命令又是什么呢?---废话,当然是程序!那么这些程序又是从哪里来 的?---废话,系统自带或是安装程序是自动安装生成的!那么这些程序又是在什么地方(哪些目录下)呢?---这……就不太清楚了吧……那么让我们来使用 一下在使用计算机是经常用到的查找方法---反向查找法来找到答案吧!就从“notepad”开始,既然说是系统自带的,那么就到系统所在的盘符查找(使 用Windows的搜索功能会吧?)好了,如果你有耐心那么就等吧。作者在此告诉你答案吧,notepad在windows的根目录下,notepad的 完整地址也就是c:\windows\notepad.exe,而CMD.EXE的完整地址也就是c:\windows\system32 \cmd.exe,当然,作者在之前提到的control和explorer等等系统工具都在这两个目录下(但是在这两个目录下是找不到 winword.EXE这个东西的,为什么呢?在2.3节会给出答案),windows根目录下的其他文件夹(除了system32)中的程序都不运行。 读者可以做一下这两个实验:1、在Windows根目录(C:\windows\,往后用统一称为%windir%,系统安装在不同的盘符Windows 的根目录则不一样,只是C\D\E\F的差别而已,另外,Windows路径不区分大小写)下新建一个文件夹,然后往里边放一个程序,然后在“运行”对话 框里输入程序名,试试看能不能启动该程序;2、直接将一个程序在%windir%,然后在“运行”对话框里输入程序名,试试看能不能启动该程序。那么以上 废话总结为:“运行”对话框只对%windir%和system32目录的程序名进行扫描匹配,如果存在则运行,否则“嘭”一声一个大红叉叉。


2.3  “运行”命令的扩展,实现自定义“命令”

到 此,可能有读者就会问了:“我知道这个又有什么用?我总不能把我想要用命令形式来打开的软件都裸奔地放在%windir%下吧!?”这个担心确实是很有道 理的,会使用C\C++来写一些小程序的读者在知道这个扫描路径后可能会自己开发一些小程序来放在%WINDIR%下玩玩,但是这样用途还是有限的。有没 有一种能够不需要将程序放在%windir%下,而且有能通过在“开始”输入命令来对其进行调用(打开)呢?办法是有的,经过作者两年前的不断摸索,总结 出了两种方法。


2.3.1  通过修改注册表实现自定义“命令”
这 也是一些工具软件让用户在“运行”对话框实现快速启动的方法,作者见身边的人用过,所以分析(在别人的电脑上干的)了一个这种软件的行为和实现方法,结合 网上查找的资料,也就总结了这个方法。在“运行”中输入  “regedit”(不带引号)并运行,然后按照“HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows \CurrentVersion\App Paths”依次展开左边的文件夹,如下所示

 


在“App Paths”项下就可以看到很多以“.EXE”结尾的子项,其中包括


等 等,读者看到winword.exe了吧,那就是为什么我们在%windir%和system32目录下都找不到winword.exe而有能够通过“运 行”对话框来打开word的原因了。读者可以从中选一个“App  Paths”子项中的文件名在“运行”中输入运行试一试,保证都能够运行。其中子项的键值就决定了该程序的路径,以作者的firefox为例:
 


默 认键值的数据就是可执行程序的完整路径(包括所在文件夹和程序名),Path键值的数据就是可执行程序所在文件夹。那么,这个思路就很清楚了,如果需要添 加自己的程序(eg. D:\TEST\AAA.EXE)就在“App  Paths”项下新建一个子项“AAA.EXE”(不包括引号),然后在修改“AAA.EXE”项下的(默认)键值的数据为“D:\TEST \AAA.EXE” (不包括引号),新建一个名为“Path”REG_SZ类型的键值并修改其数据为“D:\TEST\”  (不包括引号,下文中不再强调,如果需要加入引号,会做特别说明)。
虽然这样能够在“运行”对话框输入程序名称来运行自己的程序,但是每添加一个 程序就要修改一次注册表,打开注册表还要翻半天才找到“App  Paths”,这是苦力活,这是电脑应该做的事情,明显不能让人来干!那么怎么解决呢?---批处理命令、vbs都可以,作者此处不给出详细的代码(因为 接下来要介绍更好的方法),只是提供一个脚本的编写思路(有很多种方法的)给会使用BAT或者VBS的读者进行实践(以BAT为例):将要在注册表里 “App Paths”注册的程序作为参数(%1)传递给BAT脚本,使用 ~dpnx 和 ~dp  将程序完整路径和程序所在文件夹提取出来,然后使用REG ADD命令将提取的信息导入这册表就可以了。

接下来谈谈修改注册表来达到通过“运行” 对话框快速打开程序的弊端,打开程序是没有问题了,那如果要经常打开一个文件夹呢?如果我们照搬前边在注册表里注册程序的方法,那么在“运行”里输入文件 夹名字的时候无疑就会“嘭”一声,然后一个红叉叉!原因很简单,“App  Paths”目录下只存放可执行程序的路径,而文件夹不是程序……那要打开文件夹怎么办呢?不急,接下来说。


2.3.2  通过在%windir%下创建快捷方式实现自定义“命令”
这 是作者在2009年的某一天,瞎逛%windir%(以前很喜欢逛这个地方,微软给力,支持Windows,支持微软!)时摸索出来的,操作比前边的注册 表简单的多,而且最主要是能够打开指定的文件夹!很多读者可能已经猜到改怎么做了,对,就是将一个程序或这文件夹的快捷方式放到%windir%下,然后 在“运行”对话框中输入快捷方式的名称(不需要后缀,后缀的问题,接下来会提到),回车!怎么样?不错吧!在此,作者顺便向读者介绍一个Windows操 作使用鼠标和键盘组合(鼠标和键盘操作也是大有学问的,有时间作者也会整理出一片文章和大家分享)来创建快捷方式的一个小技巧:按住Alt键,然后用鼠标 拖拽(按住左键移动鼠标)需要创建快捷方式的目标(可以是任何文件),如下图所示:
 


所以就可以使用这种方法创建快捷方式了,将需要在%windir%下创建快捷方式的目标按住Alt后拖拽到%windir%下,然后改快捷方式的名字就可以在“运行”中用命令的形式调用了(这里就不需要上图了吧?)。
现 在来谈一谈后缀名的问题,如果自己创建的快捷方式和系统工具的默认名称重复了这么办?作者做了试验,将两个文件名字一样,但是后缀不一样(例如 AAA.EXE和AAA.LNK)的文件放在%windir%下,在“运行”输入AAA,那么系统默认运行AAA.EXE,因为EXE的是AAA的默认后 缀名,其他文件后缀作者就没有做过比较,读者可以亲自验证。

好了,现在又有一个问题了,如果每次要在%windir%创建一个快捷方式,那么就要 打开%windir%一次,虽然不想修改注册表那么麻烦,但这些都是重复的工作应该让电脑来做这些工作,我们希望的是点点鼠标输入个想要的命令名就能够在 “运行”对话框中输入自己的命令了,如何实现?在第3章中作者会给出完整的解决方案。


3  进一步简化在%windir%下生成快捷方式的操作
3.1  简化在%windir%下生成快捷方式操作的探索过程
如果读者对探究过程不感兴趣,可以直接跳到3.2节。
如果读者是Windows用户,那么相信读者一定都用过右键菜单里的“发送到”这个功能吧?
 


“发 送到”选项里边有一个“桌面快捷方式”选项读者可能经常用吧,那么有这么个思路,既然能够发送到桌面快捷方式,那么能不能发送到%windir%快捷方式 呢?经过作者的不断探究,得到的答案是肯定的。探索的过程相当繁琐而漫长,花了两、三个星期的时间才完成了从解析文件路径到基本成型的脚本,篇幅有限,不 赘述过程,只阐述结果。读者看到的发送到选项其实是一个文件夹(此文件夹默认隐藏),文件夹的位置是“%userprofile%\sendto”(在 “运行”对话框中输入“%userprofile%\sendto”就可以打开了,运行中打开后就可以看到“发送到”的文件夹具体位置 了)。%userprofile%又是什么东西?它和%windir%一样,是一个系统的环境变量,当然这又是另外一个话题了,也是很有用的东西。

那 么,找到了地方就好办了,里边都是类似快捷方式的东西(0字节!),按照前边的思路,和SendTo文件夹里的东西,如果我们在这里放一个文件夹的快捷方 式会这么样?---对的,如果我们对一个文件使用修改后的“发送到”,然后指向我们扔到“SendTo”文件夹的快捷方式,那么结果就像向我们平时往U盘 里发送(其实是复制)文件一样,只是文件复制到了我们设定的文件夹的位置。那这又有什么用呢?我们要发送的是文件的快捷方式到%windir%,又不是文 件本身---当然有用!看到“桌面快捷方式”这个东西没?它没有看执行代码(0字节),但是它指向一个可执行程序,那么如果我们在SendTo文件夹里放 一段脚本或程序什么的就可以对我们点击的文件进行操作了!会使用BAT的读者可能就知道,当我们点击一个文件时,其实就得到了一个参数---%1,这个参 数就是当前所点击的文件的路径信息,对%1进行操作就可以实现在%windir%下创建%1的快捷方式了。具体如何实现,作者就不在此赘述了,提供一个思 路,然后给出全部代码(人不需要做重复的活,重复的活让电脑干):BAT不能直接创建快捷方式,所以我们需要能够创建快捷方式的脚本---VBS,而 VBS实现参数传递有不如BAT那么方便(准确的说应该是作者的VBS学艺不精吧),所以就将BAT和VBS结合起来,使用BAT得到参数,再用BAT生 成创建快捷方式的VBS脚本,运行VBS脚本,完工(其中很多步骤的省略了,感兴趣的读者可以分析一下实现代码)。


3.2  简化在%windir%下生成快捷方式操作的批处理文件代码
将 以下给出的代码完整地复制、粘贴到一个记事本(notepad)中,然后另存为,文件名为“SendToWindir.bat”---注意后缀 名.BAT,再双击运行刚才保存的SendToWindir.bat,如果运行成功那么就会在“%userprofile%\sendto”生成一个同样 名字的文件。读者右击某个文件,然后就可以在“发送到”选项里看到多了一项“SendToWindir”。使用方法和“发送到”->“桌面快捷方 式”的操作类似,只是多了个输入名称的过程,看提示就会了,将一个文件的快捷方式发送到%windir%后就可以在“运行”对话框输入对应的名称来打开文 件了,程序、文件夹或文档都可以。源码如下:
rem SendShortcutToWindir
@echo off
color 17
cls
:copy this batchfile to SendTo directory of the user
cd /d %userprofile%\sendto
if not exist %~nx0 (
echo batchfile does not exit, copying file to %userprofile%\sendto\ ...
copy %0 "%userprofile%\sendto\%~nx0"
:type %0>"%userprofile%\sendto\%~nx0"
echo Done! Now, exit this program and check the SendTo options of right-click menu
pause
exit
)
echo.
echo.
title SendShortcutToWindir
echo                             ************************
echo                               SendShortcutToWindir
echo                             ************************
echo            **********************************************************
echo            *                    designed by Gavin                   *
echo            *         created time:2009-11-10 星期二 14:58           *
echo            *                   all rights reserved                  *
echo            **********************************************************
:set path=%~dp1
:echo %path%
cd /d %~dp0
:********key statement to resolve the violation of quotation marks in the path *****
set str="%~dpnx1"
:***********************************************************
echo %str%
set name=%~n1
echo default name: %name%
echo input the shortcut name:
set /p name=
set ShortcutTargetPath=%str%
:************change this parameter can make it different...*********************
set ShortcutPath="%windir%\%name%.lnk"
set IconLocationPath=%str%
:***********the Icon of the created shortcut is the Icon of the target file.************
set HotKey=""

echo Set WshShell=WScript.CreateObject("WScript.shell")>WindowsShortcut.vbs
echo Set Shortcut=WshShell.CreateShortCut(%ShortCutPath%) >>WindowsShortcut.vbs
:situation1
:***********with quotation marks in %1
echo Shortcut.Hotkey = %HotKey% >>WindowsShortcut.vbs
echo Shortcut.IconLocation=%IconLocationPath% >>WindowsShortcut.vbs
echo Shortcut.TargetPath=%ShortcutTargetPath% >>WindowsShortcut.vbs
echo Shortcut.Save >>WindowsShortcut.vbs
"%SystemRoot%\System32\WScript.exe" WindowsShortcut.vbs
:pause
del WindowsShortcut.vbs /q /f
echo Done!
exit

:situation2
:***************without qoutation marks in %1
echo Shortcut.Hotkey = %HotKey% >>WindowsShortcut.vbs
echo Shortcut.IconLocation="%IconLocationPath%" >>WindowsShortcut.vbs
echo Shortcut.TargetPath="%ShortcutTargetPath%" >>WindowsShortcut.vbs
echo Shortcut.Save >>WindowsShortcut.vbs
"%SystemRoot%\System32\WScript.exe" WindowsShortcut.vbs
:pause
del WindowsShortcut.vbs /q /f
echo Done!
exit

如果使用缺省名称(当前文件名,不包括后缀)的话,直接回车即可。如果“命令”名重复,则直接覆盖并且不返回提示,脚本运行效果图如下:
 

在 本章最后提的一点就是Windows版本的问题,以上的操作在Windows XP下进行完全没有问题,但是在Windows  7下就不能正确运行了。对于Windows 7的用户,由于windows  7使用NTFS文件系统,Windows为了保护系统,而默认设置用户对SendTo文件夹没有权限,所以用户打不 开%userprofile%\sendto这个文件文件夹,更不能往里边存放文件。解决办法就是完全取得文件夹的权限,然后再运行作者提供的bat文件 就可以了。


4  结论
本 文通过介绍如何实现在Windows下通过在“运行”对话框中输入自定义“命令”(作者认为并不是真正的命令,而只是一种有指向性的代码而已)来运行/打 开任意文件,提出了一种能够通过键盘的输入来提高计算机使用效率的方法。自从作者完成了发送到%windir%快捷方式的脚本后,就不需要在桌面上显示任 何图标了,对于Windows启动速度有要求的读者也可以尝试不在桌面显示图标,这样可以提高Windows进入桌面时的加载速度。在文章最后,作者再提 一点使用“运行”对话框技巧,虽然我们发送到%windir%的只是快捷方式,但是我们可以将其当作真正的命令使用,就是这些命令是可以带参数的,举个例 子,如果我们将IE浏览器的可执行文件发送到%windir%快捷方式并命名为“IE”,如果我们在“运行”对话框中输入“IE”,当然就打开了一个IE 的窗口,如果我们输入“IE  www.baidu.com”呢?对的,就打开了一个百度的首页(当然,前提是要已联网,不然就会得到ERROR404)。本文只是介绍了实现打开/运行 文件的方法,如果会使用BAT或VBS或Windows编程的读者结合自定义的脚本/程序,相信则不仅仅可以打开/运行一些文件而已,还可以执行一系列的 自动化操作而不影响到%windir%的整洁(快捷方式很小的,而且很容易整理),最后一个例子,作者不经常关机,而是经常待机,所以写了一个脚本,并且 做成了自定义“命令”,所以每次需要待机就输入“standby”就可以完成,“命令”简洁明了。如果读者正在使用电脑进行着重复的操作,那么就可以想一 想如何让电脑来帮助你完成这些重复的动作了。
最后,重要的不是结果,而是过程,希望本文能够给读者平时在使用windows时带来一些启发,本文涉及到的批处理、VBS、环境变量、系统自带工具等内容,网上有很多资料可以参考,搜索相应关键字就可以了。如果本文有错误或不妥的地方,请读者不吝赐教,谢谢!

使用批处理进行数据智能备份与同步

(版权所有,转载请注明)

Gavin Chou

2013-01-21

1.    引言
硬盘和U盘等存储设备日趋白菜的价格,很多人都有了使用移动硬盘或者U盘来备份数据的习惯(对于经常做软件工作的,这个是非常重要的呃,深有体会),备份数据的重要性就不说了,平常用的电脑硬盘说不定哪天就罢工了,硬盘不值钱,值钱的是数据。通常在备份数据的时候,我们都是直接将待备份的文件夹直接复制到备份目录,然后往往过了一小段时间就会出现是否覆盖的提示弹窗,当然是覆盖了,然后还有勾选了“以后使用同样的操作”,但是过了一段时间,可能又会出现覆盖的提示(好像每个文件夹都要问一次,我记得是这样的,很久没用这种方法了),效率很不高,另外,如果修改过待备份夹的目录结构:新增加文件当然没事,就让它复制好了。但是如果是删除,或者移动了一些文件,那么备份的时候只是负责覆盖,并不会检查/删除备份目录下应该被删除或者移动的文件,大部分情况下我们是希望备份目录应该和待备份目录所有的目录结构和文件保持完全一致(当然还有一些特别的情况,后边会提到,如何处理这种情况),是不是有方法能使在拷贝数据的时候不用坐在电脑旁边等?能够自动调整备份目录的目录结构?答案当然是肯定的。重复的工作永远都应该让电脑来干……接下来,逐步介绍用Windows自带的命令解决这个备份、数据同步的问题。


2.    使用命令实现全部文件静默备份
静默就是不会出现是否覆盖的提示,而是在后台默默进行备份,在Windows下,要实现这种完全覆盖的复制方式有一个批处理命令(什么?你不懂批处理?先看看本文最后边的附录1吧)可以实现,就是xcopy

xcopy "src" "dst" /r/c/y/h/d>>%date:/=-%.txt 
echo done
notepad.exe %date:/=-%.txt

上边命令行第一行的src 是待备份的目录,dst 是备份目录,如果目录的路径含有空格的话必须用""括起来如
xcopy "d:\my documents" "k:\backup\my documents" /e/r/c/y/h/d>>%date:/=-%.txt
按照自己的实际情况修改上边的代码相应部分,再复制到记事本里,然后另存为backup.cmd,双击backup.cmd,备份就开始了
/e/r/c/y/h 复制的参数解释
    /e 表示空目录也复制,
    /r 只读文件也覆盖 
    /c 在copy出错时,继续复制 
    /y 静默复制(覆盖的时候不需要确认)
    /h 隐藏的文件也复制
    /d 如果目标文件存在,只复制原文件修改日期比其更后
    xcopy的其他参数可以在cmd里输入xcopy/? 查看
后边的 >>%date:/=_%.txt 就是把复制的结果(复制了哪些文件)保存到一个以当前日期命名的文本日志文件
第二行是操作完成的提示
第三行是打开日志文件

上边的三行命令很简单,执行的动作也很简单,但是也只是完成了一个引言里提到的一个功能,就是开始备份之后就可以不用管了,而且只复制更新过的文件,直到备份结束为止,结束后我们还能得到一个待备份目录的目录树,备份日志也相对粗糙,因为都没进行什么处理。

3.    智能备份
3.1.    比较理想的备份策略

高效的备份要讲究一定的策略,前边给出的解决方案虽然可以省掉我们点鼠标用的时间,这并还没有达到最好、最通用的效果,我们在备份的时候最理想的情况就是(这些仅仅是我在实际备份数据时遇到的问题、需求):
1)    原来备份过的文件如果没有更改就不重写到备份目录
2)    待备份目录下有新的文件产生,将新的文件复制到备份目录(当然路径要保持一致)
3)    原来已经备份了的文件,但是又经过了修改,就是说待备份目录下的文件比原来已经备份的文件要“新”,就overwrite备份目录下的该文件(以上3条统称为增量备份)
4)    一般,我们希望可以使备份目录与待备份目录保持一致,例如:待备份目录在上次备份的时候有15个一级子目录和20个文件(就是在待备份目录下能直接看到的所有东西),在一段时间的使用后,待备份目录下变成了10子目录,10个文件,那么如果仅仅使用复制的方法是只能将待备份数据复制到备份目录下的,而备份目录下多余的文件、文件夹是不会自动合并或删除的,这时需要将多余的文件|目录合并---删除,这个称为同步备份
5)    在某些时候,我们希望两个文件夹之间“互通有无”(我把这种方式称为 增量-同步备份),比如说手机等移动设备的SD卡上的音乐文件夹和电脑上的音乐文件夹,有时我们会在手机上下载一些音乐,有时我们会在电脑上下载一些音乐,久了之后两个文件夹的内容就会有重复的文件和对方都没有的文件,这个情况,我们希望使这两个文件夹
6)    有时候,我们在备份某个文件夹的时候并不希望备份其下的某一些文件或文件夹,如*.bak *.tmp *.dump 等这些临时文件或者\temp\ \tmp\ 等这些临时文件夹或则用户不想备份的东西,那么在复制的时候就需要将这些东西排除(exclude)
7)    ……

3.2.    备份算法
怎么样才能达到以上提出要求,根据我的经验和仅有的知识,得出的解决方案思路(算法)就是:
1.    完成增量备份:遍历待备份目录下所有文件(注意是所有,包括其所有子目录及子目录下的文件),和备份目录下的文件进行对比(目标是否已经存在、是否被修改)。如果不存在则直接复制;存在,则查看目标的修改日期并和源文件的修改日期进行对比,如果源较新,那么就覆盖目标文件。
2.    完成同步备份:如果需要将目标文件夹同步成和源文件夹一模一样,在完成增量备份后,遍历一遍(我也不想遍历的,但是这必须要遍历……),和源文件夹下的所有文件|文件夹进行对比,如果在源文件夹下找不到与存在目标文件夹的文件相同的文件,那么就删除目标文件夹下的该文件,当完成目标文件夹下的文件匹配后,清空目标文件夹下的所有空子目录。3,增量-同步备份:两个文件夹,以其中一个为源,令一个为目标,进行一次增量备份,然后swap(交换)源和目标文件夹,再进行一次增量备份。
3.    添加excludelist
4.    抓虫子(debug),egg pain……

3.3.    功能实现
有了算法,就要码了,文章开头就说过,这些个功能用批处理实现,也就是对开头的那三行批处理进行稍微的扩展。那么就开始码吧,首先完成遍历源文件夹,取文件路径,然后…………………(此处省略200000字种代码的艰辛劳作过程,不要轻易就去码代码,伤神、伤身、伤心,还不如打dota,哈哈)………………
最后,好了,经过8天8夜废寝忘食不断地调试,终于完成了一个比较通用的批处理文件(没经过充分的调试、检验,也不敢拿出来跟大家分享,毕竟这涉及到宝贵数据的问题~),我把它命名为Sync_Data.cmd,详细代码见文末的附录2
接下来介绍一下这个东西怎么用
有两个用法,一个就是以命令行的方式使用,另外一个就是直接双击运行,如果之前有看过我写的《Windows“运行”自定义“命令”的实现》这篇文章,而且对批处理有一定了解的推荐使用第一种方法以命令的方式运行,设置了最多5个输入参数(用空格分隔)
使用命令的语法: 
sync_data ["srcPath" "dstPath" [1|0] [y] [excludelist]]|[?]
前两个参数不解释
参数 [1|0]         表示复制完后是否检查并合并目标文件夹使其和源一样
参数 [y]           表示不显示确认信息
参数 [excludelist] 表示要排除的文件列表
参数 [?]           显示help信息

3.3.1.    使用示例:
以下的 sync_data 指的是sync_data.cmd这个批处理的完整路径,如果不会使用cmd这个命令提示符窗口的,可以将代码放到记事本里按自己的需求进行编辑,编辑好后另存为.CMD 或者.BAT文件,双击运行该文件即可。
显示help信息:
sync_data ?

实现同步备份(让目标文件和源文件夹一模一样):
sync_data "e:\videos" "k:\backup\videos" 1 y

实现同步备份(让目标文件和源文件夹一模一样),并且要exclude一些文件和文件夹:
sync_data "e:\videos" "k:\backup\videos" 1 y "e:\videos\sports"+"e:\videos\guitar\tutorial.flv"

实现增量-同步备份
sync_data "e:\videos" "k:\backup\videos" 0 y
sync_data "k:\backup\videos" "e:\videos" 0 y

实现多个目录连续备份
sync_data "e:\folder1" "k:\backup\folder1" 1 y
sync_data "e:\folder2" "k:\backup\folder2" 1 y
sync_data "e:\folder3" "k:\backup\folder3" 1 y

其他的用法可以自己发挥,组合其他的批处理命令

双击运行,或者直接使用不带参数的sync_data 命令,则会出现提示窗口,依提示依次输入源源文件夹、目标文件夹、是否合并、有没有exclude的文件,最后确认信息。
本来想一张图都不上的,算了,还是上一张图吧……


3.3.2.    说明:
1)    文件名含有不能显示的ASCII码(码值不是32到126之间的,这些码也是不能用键盘敲出来的,一般应该是程序自动命名的时候弄的,真不知道写这些程序的人怎么想的,这种奇葩文件名基本上可以忽略不记),而且在win7下是不能用这些非32到126之间的ASCII码来命名文件的,我也不知道这些字符是靠手动是怎么弄到文件名上的---剪贴板?试过了,不太行,可能是历史遗留问题),该文件不会被正确复制(error: file not found),不能正确复制的错误会被记录在日志文件的开头部分(error部分)
2)    日志文件记录备份目录(目标目录)所有的改动,包括:
1,有新文件复制到备份目录的文件;
2,在备份目录下的文件被overwrite的文件;
3,在备份时产生的错误(如果有错误的话)
3)    通过了多次残酷的极端条件测试:
1,文件名包含各种特殊字符(~!@#$%^&()_+-=,.;'[]{})都可以被顺利复制(中文当然不在话下了……),花了好几天来调试……
2,长文件名(深层次目录)测试(完整文件名长度最长255个字符,这是windows下路径长度的极限了);
4,200多次不同的调试测试
5,……
4)    开启exclude选项会影响备份效率(即使不能看出多消耗了多少时间),因为要不断的将待备份文件进行查找匹配,建议在需要排除的文件较多或者文件较大的时候开启exclude选项,如果文件数量很少,或者文件不是很大,则使用复制后再进行手动删除,或者使用如下组合命令实现
sync_data "src" "dst“
del file1
del file2
...
rd /s/q folder1
rd /s/q folder2
...
file1 file2 folder1 folder2 是已备份在目标文件夹里的文件(夹)的完整路径(可以通过批出里自动生成,此处省去生成这些路径的方法,详细请看sync_data的代码)
5)    不备份空目录,也不打算添加这个功能,如果需要这个功能的可以使用以下组合命令行实现:
sync_data "src" "dst" 1 y "excludelist"
xcopy "src" "dst" /e/s/y/h/d>nul
6)    本批处理使用xcopy作为copy的媒介,如果对copy过程有什么特殊要求,可以对本批处理在使用xcopy的相应部分进行修改
7)    友情提醒:不到万不得已,千万不要使用特殊符号(~!#$%^&_+-=;')来命名文件,不然有时候在使用一些软件的时候出问题都不知道是什么回事,空格也尽量不要用,用下划线代替,有时候一些程序(或者脚本)不能顺利读取文件,就是因为它没有对带有空格等字符的路径进行处理(还记得吗,许多程序的传入参数是用空格等一些特殊字符来进行分隔的,本来应该俩参数的,你的路径里多了些空格或者什么东西),failed,最可怕的是,有时很难看出是什么问题……

这个批处理,在运行的时候,合理使用CPU,查找在高速查找匹配的时候用到40% CPU资源(core i7 2670,8GB RAM),当听到CPU风扇猛的在转的时候,就是文件查找速度最快的时候,也是其效率最高的时候,所以不要觉得很奇怪为什么风扇叫的这么厉害。
(版权所有,转载请注明)

 
附录1:
[转载] 批处理是什么?能干什么?转自批处理之家http://www.bathome.net/thread-20-1-1.html
批处理文件是指文件后缀名为“.bat”的文件,它的作用是可以一次批量执行大量的命令。这种文件在dos时期曾被大量使用,win9x时期也有,但已经开始少用了,最典型的是autoexec.bat这个文件了。

1.什么是批处理文件?批处理文件的作用是什么?
批处理文件(Batch File,简称 BAT文件)是一种在DOS 下最常用的可执行文件。它具有灵活的操纵性,可适应各种复杂的计算机操作。所谓的批处理,就是按规定的顺序自动执行若干个指定的DOS命令或程序。即是把原来一个一个执行的命令汇总起来,成批的执行,而程序文件可以移植到其它电脑中运行,因此可以大大节省命令反复输入的繁琐。同时批处理文件还有一些编程的特点,可以通过扩展参数来灵活的控制程序的执行,所以在日常工作中非常实用。

2.批处理文件的格式是什么?
批处理文件起源于DOS时代,在DOS时代的扩展名为.bat(即是batch的缩写),可使用Copy con、Edit、WPS等DOS程序来编辑。
经时代的发展,现今批处理文件已经不止支持DOS下的程序,同时也支持Windows环境程序的运行,在Windows NT以后的平台中,还加入了以.cmd为扩展名的批处理文件,其性能比.bat文件更加优越,执行也与.bat文件一样方便快捷。
注:由于.bat文件是基于16平台下的程序,在Windows NT及以后的32位中运行时偶尔会出现堆栈溢出之类的错误,所以建议在新的系统中尽可能的采用.cmd扩展的批处理文件代替.bat的文件。

3.如何来编写批处理文件?
其实编写批处理文件并没有什么编程环境的要求,任何一个文本编辑器都可以用来编写批处理文件,像DOS下的Edit、WPS以及DOS自带的Copy命令的扩展copy con命令就可以编写,Windows下的记事本、写字板等。

4.批处理文件的工作平台。
由于批处理文件其实就是一个命令的集合,所以批处理文件的工作平台是由这些命令所工作的平台来决定,今天我们在这里主要研究的是Microsoft环境下的批处理文件(.bat和.cmd文件),所以这里的平台,当然也就是指Microsoft的DOS和Windows系统。

5.批处理文件的应用。
现今Windows环境已经如此普及,程序的运行只要点击几次鼠标就可以完成,所以造成很多人都已经不了解批处理文件的作用,特别是那些新接触电脑的用户,而更多的了解它的人却是那些程序设计人员,但不可否认,批处理文件有很多优点是其它程序所无法比拟的,最主要的优点就是编写环境的宽松,编写人员能力要求较低。
其实我们经常可以接触到批处理文件,只是我们很少注意而已,像Windows 9x启动时加载的Autoexec.bat文件就是一个批处理文件,当然这个批处理文件是一个比较特殊的批处理文件,至于详细这个文件的相关介绍,大家可以到网上查看相关的文档。另外就是我们安装程序的时候,经常可以看到有一个黑色的命令行窗口跳出来,这时其实大部分可能性它执行的就是一个批处理文件。

 
附录2:
将以下批出里完整代码复制到记事本里,另存问sync_data.cmd(版权所有,转载请注明)
rem data synchronizer
:start
cls
@echo off
cls
color 17
echo.
echo.
title data synchronizer - Gavin
echo                             ************************
echo                                 data synchronizer
echo                             ************************
echo            **********************************************************
echo            *  Description: sync the files ^& folders of 2 folders    *
echo            *  Version: 2.1                                          *
echo            *  syntax: sync_data ["srcPath" "dstPath" [1^|0] [y]      *
echo            *                     [excludelist]]^|[?]                 *
echo            *                    Designed by Gavin                   *
echo            *            Created time: 2013-01-08 Tue 20:21          *
echo            *                   All rights reserved                  *
echo            **********************************************************
cd /d %~dp0
rem versions:
rem version 1.0: 2013-01-08
rem              1, smart-sync.
rem version 2.0: 2013-01-17 
rem              1, print errors in log file, rearranged log file's contents
rem              2, add arguments capblility
rem version 2.1: 2013-01-19 
rem              1, add exluding list of files or folders to be copied
rem version 3.0: 2013-01-xx
rem              1, rewrite/refactor the core code, optimized the efficience

rem before overwriting the destination file, the file attributes should be 
rem checked, say, the date when the file is last modified, if the target file is 
rem as "new" as the file to be backupped then abort overwriting, skip to next 
rem file  

if "%1" equ "?" goto instruction
if "%2" equ "" (echo.&echo press any key to continue... & pause>nul)
echo Instruction:
echo ^(put the following in google-translate if English bothers you...^)
echo 1, this batch file is used for synchronizing data between 2 folders
echo    a source and a destination folder, data^(files^|folders^) of the source 
echo    will be copied to the dest..
echo 2, a log file will be generated, and the log will show up when sync. is 
echo    done. any file changes, errors, ect. are recorded.
echo 3, a merging option is availabe, if activated, the dest. folder will be 
echo    maded completely the same as the source folder, it is very useful while  
echo    backuping^(both files and direcory structure, surely, some data of dest. 
echo    may be deleted^).
echo 4, if merging option is not activated(just copy new files to the 
echo    destination), run this bat onece, then swap the source and dest., run 
echo    again, which can make each of the 2 folders get what it do not have of 
echo    the other before sync., it is very useful while sync. 2 folders, say, 
echo    music files between your mobile devices and computer.
echo 5, to learn more about this batch file, read the comments and the code of 
echo    it. you may find more ways to use it.
echo 6, the author does not take any responsibility for the ueser's data loss, 
echo    tests are recommended before you first using it to sync..
echo 7, contact the author: gavineaglechou#gmail.com^(plz. replace ^# with ^@^).
if "%2" equ "" (echo.&echo press any key to continue... & pause>nul)
echo. 
rem Attention & Instruction(for advanced user):
rem 1, "setlocal enableddelayedexpansion" has been invoked, if there is any 
rem "!" - exclamation mark contained in the file|folder name the "!" will be 
rem ignored, which will cause a problem - "file not found", meaning that the 
rem file|folder will be skipped, to resolve the problem is to remove "!" in the 
rem file|folder name (by renaming it) and then process
rem hence, try to name the files|folders in the proper style:
rem DO NOT USE UNEXPECTED SPECIAL CHARATERS IN THE FILE|FOLDER NAME
rem OR IT WILL COST A LOT TO DEAL WITH THAT CRAP!!! FREQUENTLY CHECKING THE  
rem NAMES LOSES BOTH EFFICIENCE AND SIMPLICITY!

set "crap=crap"
set "log=sync_log.txt"
set "src=%1"
set "dst=%2"
:copying
if "%1" neq "" (
    if "%1"=="?" (
        goto help
    )
    if "%2" neq "" (
        goto choice1
    )
)
:input
set "src=E:\BAT"
set "dst=j:\BAT"
echo PLEASE INPUT THE PATH AS THE PROMPTS STRICTLY^! 
echo source to be synced:(e.g D:\My documents)
set /p "src="
echo. & echo destination folder:(e.g H:\backup\Documents)
set /p "dst="
:choice1
rem remove the quotation mark, if there is any
set "src=%src:"=%"
set "dst=%dst:"=%"

if "%3" equ "" (
    echo. 
    echo files in destination: "%dst%" 
    echo but not exist in source: "%src%" 
    echo will be removed^(merged^) after copying flies from source to destination
    set /p "choice=merge the folders of "%dst%"?[y/n]"    
    setlocal enabledelayedexpansion
    if "!choice!"=="y" (endlocal & set "merged=1" & goto continue1)
    if "!choice!"=="Y" (endlocal & set "merged=1" & goto continue1)
    if "!choice!"=="n" (endlocal & set "merged=0" & goto continue1)
    if "!choice!"=="N" (endlocal & set "merged=0" & goto continue1)
    endlocal
) else (
    if "%3"=="1" (set "merged=1" & goto continue1)
    if "%3"=="0" (set "merged=0" & goto continue1)
    shift /3 & shift /3 & shift /3 & shift /3
)
goto choice1

:continue1
set "excluded=0"
set "excl=%5"
if "%5" equ "" (
    if "%4" neq "" goto choice2
    echo.
    set /p choice=any files^|folders to be excluded while copying[y/n]
    setlocal enabledelayedexpansion
    if "!choice!"=="y" (endlocal & set "excluded=1" & goto inputList)
    if "!choice!"=="Y" (endlocal & set "excluded=1" & goto inputList)
    if "!choice!"=="n" (endlocal & set "excluded=0" & goto choice2)
    if "!choice!"=="N" (endlocal & set "excluded=0" & goto choice2)
    endlocal
    goto continue1
) else (
    if exist __xList__ (
        del __xList__ /f/q/a
    )
    setlocal enabledelayedexpansion
    set "excl=!excl:"+"=|!"
    set "excl=!excl:" +"=|!"
    set "excl=!excl:" + "=|!"
    set "excl=!excl:"+ "=|!"
    set "excl=!excl:"=!"    
:genList1
    for /f "tokens=1,* delims=|" %%a in ("!excl!") do (
        echo.%%a>>__xList__
        set "excl=%%b"
    )
    if "!excl!" neq "" (goto genList1)
    endlocal
    set "excluded=1"
    goto choice2
)

:inputList
echo e.g, input "E:\videos\video 1.flv"^+"E:\videos\video 2.flv"^+"E:\videos\sport\"
echo the files video 1.flv ^& video 2.flv and the folder sport won't be copied
echo what will be excluded?
set /p excl=
if exist __xList__ (
    del __xList__ /f/q/a
)
set excl=%excl:"+"=|%
set excl=%excl:" +"=|%
set excl=%excl:" + "=|%
set excl=%excl:"+ "=|%
set "excl=%excl:"=%"
:genList2
for /f "tokens=1,* delims=|" %%a in ("%excl%") do (
    echo.%%a>>__xList__
    set "excl=%%b"
)
if "%excl%" neq "" goto genList2

:choice2
echo. 
echo data in "%src%" will be copied to "%dst%"
if "%merged%"=="1" (
    echo files^|folders exist in "%dst%" but not exist in "%src%" will be removed^(merged^)
)
if "%excluded%"=="1" (
    echo.
    echo the following list of files^|folders will be excluded while copying:
    type __xList__
)
echo. 
if "%4" equ "" (
    set /p "choice=WARNING: is all info. correct?[y/n]"
    setlocal enabledelayedexpansion
    if "!choice!"=="y" (endlocal & goto continue2)
    if "!choice!"=="Y" (endlocal & goto continue2)
    if "!choice!"=="n" (endlocal & shift /1 & shift /1 & shift /1 & goto start)
    if "!choice!"=="N" (endlocal & shift /1 & shift /1 & shift /1 & goto start)
    endlocal
    goto choice2
) else (
    if "%4"=="y" (goto continue2)
    if "%4"=="Y" (goto continue2) else goto input
)

:continue2
echo synchronization is in progress, DO NOT close this cmd. window before it
echo has finished.
echo start at %date% %time:~0,-3%
rem setup log file
for /f "delims=<" %%a in ("%dst%") do (
    set "log=%%~da"
)
if not exist "%log%\Sync_Log" md "%log%\Sync_Log"
set "logName=%date:\=-%_%time::=_%"
set "logName=%logName:~0,-3%"
set "err="%log%\Sync_Log\%logName%_Error.txt""
set "log="%log%\Sync_Log\%logName%.txt""
set "logName="%logName%.txt""

echo this log file path: %log%>%err%
echo.%date% %time:~0,-3% from "%src%" to "%dst%">>%err%
echo. >>%err%
echo ====================================================================>>%err%
echo errors: >>%err%
echo paths or files specified are not recognized, please check and deal with them mannually>>%err%
echo. >>%err%
echo ====================================================================>>%log%
echo details:>>%log%
echo start at %date% %time:~0,-3%>>%log%
echo. &echo %date% %time:~0,-3% copy files from "%src%" to "%dst%"
echo. >>%log%
echo %date% %time:~0,-3% copy files from "%src%" to "%dst%">>%log%
rem get all the paths of the files in the folder to be backuped
for /f "tokens=* delims=" %%n in ('dir "%src%" /b/a-d/s') do (
    rem dateModified
    set "srcTime=%%~tn"    
    set "srcName="%%n""
    setlocal enabledelayedexpansion
    rem set "dstName="!srcName:D:\My_Documents\Knowledge\Computer\Bat=E:\bat!""
    for /f "delims=<" %%c in ("!src!") do (
        for /f "delims=<" %%d in ("!dst!") do (
            set "dstName=!srcName:%%c=%%d!"
        )
    )
    rem echo !dstName!
    if exist !dstName! (
        rem echo exists, get the last-modified time of the existed file 
        for /f "tokens=* delims=<" %%a in (!dstName!) do (
            set "dstTime=%%~ta"
            rem echo src !srcTime! dst !dstTime! & pause
        )
        if "!srcTime!" neq "!dstTime!" (
            rem echo old version exists, overwrite it.
            rem echo.!srcTime! !dstTime!
            if "!excluded!"=="1" (
                (echo f|xcopy !srcName! !dstName! /y/r/c/h/exclude:__xList__>nul) || (
                    set "error=true"
                )
            ) else (
                (echo f|xcopy !srcName! !dstName! /y/r/c/h>nul) || (
                    set "error=true"
                )
            )
            if defined error (
                echo copy_failed !srcName!>>!err!
                echo copy_failed !srcName!>>!log!
            ) else (
                echo overwrited !dstName!>>!log!
            )
        ) else (
            rem echo file not changed, skip it.
        )
    ) else (
        rem echo not exists, copy
        if "!excluded!"=="1" (
            (echo f|xcopy !srcName! !dstName! /y/r/c/h/exclude:__xList__>nul) || (
                set "error=true"
            )
        ) else (
            (echo f|xcopy !srcName! !dstName! /y/r/c/h>nul) || (
                set "error=true"
            )
        )
        if defined error (
            echo copy_failed !srcName!>>!err!
            echo copy_failed !srcName!>>!log!
        ) else (
            echo new !dstName!>>!log!
        )
    )
    endlocal
)
rem pause&exit
rem copy hidden files
echo.&echo %date% %time:~0,-3% copy hidden files from "%src%" to "%dst%"
echo. >>%log%
echo %date% %time:~0,-3% copy hidden files from "%src%" to "%dst%" >>%log%
for /f "tokens=* delims=" %%n in ('dir "%src%" /b/a-dh/s') do (
    rem dateModified
    set "srcTime=%%~tn"    
    set "srcName="%%n""
    setlocal enabledelayedexpansion
    rem set "dstName="!srcName:D:\My_Documents\Knowledge\Computer\Bat=E:\bat!""
    for /f "delims=<" %%c in ("!src!") do (
        for /f "delims=<" %%d in ("!dst!") do (
            set "dstName=!srcName:%%c=%%d!"
        )
    )
    rem echo !dstName!
    if exist !dstName! (
        rem echo exists, get the last-modified time of the existed file 
        for /f "tokens=* delims=<" %%a in (!dstName!) do (
            set "dstTime=%%~ta"
            rem echo src !srcTime! dst !dstTime! & pause
        )
        if "!srcTime!" neq "!dstTime!" (
            rem echo old version exists, overwrite it.
            rem echo.!srcTime! !dstTime!
            if "!excluded!"=="1" (
                (echo f|xcopy !srcName! !dstName! /y/r/c/h/exclude:__xList__>nul) || (
                    set "error=true"
                )
            ) else (
                (echo f|xcopy !srcName! !dstName! /y/r/c/h>nul) || (
                    set "error=true"
                )
            )
            if defined error (
                echo copy_failed !srcName!>>!err!
                echo copy_failed !srcName!>>!log!
            ) else (
                echo overwrited !dstName!>>!log!
            )
        ) else (
            rem echo file not changed, skip it.
        )
    ) else (
        rem echo not exists, copy
        if "!excluded!"=="1" (
            (echo f|xcopy !srcName! !dstName! /y/r/c/h/exclude:__xList__>nul) || (
                set "error=true"
            )
        ) else (
            (echo f|xcopy !srcName! !dstName! /y/r/c/h>nul) || (
                set "error=true"
            )
        )
        if defined error (
            echo copy_failed !srcName!>>!err!
            echo copy_failed !srcName!>>!log!
        ) else (
            echo new !dstName!>>!log!
        )
    )
    endlocal
)

:merging
if "%merged%" neq "1" goto finish
rem using the same tricks as the above, swaping dst. and src., 
rem can remove the files that have been removed, renamed or merged in the src. 
rem folder
echo.&echo %date% %time:~0,-3% merge: check the files in "%dst%"
echo. >>%log%
echo %date% %time:~0,-3% merge: check the files in "%dst%" >>%log%
for /f "tokens=* delims=" %%n in ('dir "%dst%" /b/a-d/s') do (
    set "dstName="%%n""
    setlocal enabledelayedexpansion
    for /f "delims=<" %%c in ("!dst!") do (
        for /f "delims=<" %%d in ("!src!") do (
            set "srcName=!dstName:%%c=%%d!"
        )
    )
    rem echo !srcName!
    if exist !srcName! (
        rem echo exists in src., do nothing. 
    ) else (
        rem echo file not exists in the source folder, delete it
        (del /f/q/a !dstName! 2>nul) || (
            set "error=true"
        )
        if defined error (
            echo delete_failed !dstName!>>!err!
            echo delete_failed !dstName!>>!log!
        ) else (
            echo deleted !dstName!>>!log!
        )
    )
    endlocal
)
rem check the hidden files
echo.&echo %date% %time:~0,-3% merge: check the hidden files in "%dst%"
echo. >>%log%
echo %date% %time:~0,-3% merge: check the hidden files in "%dst%">>%log%
for /f "tokens=* delims=" %%n in ('dir "%dst%" /b/a-dh/s') do (
    set "dstName="%%n""
    setlocal enabledelayedexpansion
    for /f "delims=<" %%c in ("!dst!") do (
        for /f "delims=<" %%d in ("!src!") do (
            set "srcName=!dstName:%%c=%%d!"
        )
    )
    rem echo !srcName!
    if exist !srcName! (
        rem echo exists in src., do nothing. 
    ) else (
        rem echo file not exists in the source folder, delete it
        (del /f/q/a !dstName! 2>nul) || (
            set "error=true"
        )
        if defined error (
            echo delete_failed !dstName!>>!err!
            echo delete_failed !dstName!>>!log!
        ) else (
            echo deleted !dstName!>>!log!
        )
    )
    endlocal
)
rem remove the empty folders
echo.&echo %date% %time:~0,-3% merge: check "%dst%" empty directory
echo. >>%log%
echo %date% %time:~0,-3% merge: check "%dst%" empty directory>>%log%
for /f "tokens=* delims=" %%n in ('dir "%dst%" /b/ad/s ^| sort /r') do (
    rd "%%n" 2>nul && echo removed "%%n">>%log%
)
echo.&echo %date% %time:~0,-3% merge: check "%dst%" hidden empty directory
echo. >>%log%
echo %date% %time:~0,-3% merge: check "%dst%" hidden empty directory>>%log%
for /f "tokens=* delims=" %%n in ('dir "%dst%" /b/adh/s ^| sort /r') do (
    rd "%%n" 2>nul && echo removed "%%n">>%log%
)
:finish
if exist tempname del /f/q/a tempname
echo.&echo finished sync. at %date% %time:~0,-3%
echo.&echo generate log file...
if "%excluded%"=="1" (
    del temp.tmp /f/q/a 2>nul
    setlocal enabledelayedexpansion
    for /f "tokens=* delims=<" %%n in ('type %log%') do (
        set "str=%%n"
        set "flag=1"
        if "!str:~0,1!" neq "2" (
            for /f "tokens=* delims=<" %%m in ('type __xList__') do (
                set "str=%%m"
                for /f "delims=<" %%c in ("!src!") do (
                    for /f "delims=<" %%d in ("!dst!") do (
                        set "str=!str:%%c=%%d!"
                    )
                )
                (echo %%n|find /i "!str!">nul) && (set "flag=0")    
            )
            if "!flag!" equ "1" (echo.%%n>>temp.tmp)    
        ) else (
            echo.%%n>>temp.tmp
        )
    )
    endlocal
    if exist temp.tmp (
        xcopy "temp.tmp" %log% /r/h/c/y>nul
    )
)
echo. >>%log%
echo finished sync. at %date% %time:~0,-3%>>%log%
echo ====================================================================>>%log%
rem process log
echo ====================================================================>>%err%
echo. >>%err%
echo ====================================================================>>%err%
echo excluded files and folders:>>%err%
type __xList__>>%err%
echo ====================================================================>>%err%
echo. >>%err%
type %log%>>%err%
del %log% /f/q/a 2>nul
del __xList__ /f/q/a 2>nul
del temp.tmp /f/q/a 2>nul
ren %err% %logName%
echo.&echo synchronizaion logs have been shown.
echo.&echo close this window to exit...
echo. 
notepad.exe %log%
:end
pause>nul
exit

:instruction
echo Instruction:
echo ^(put the following in google-translate if English bothers you...^)
echo 1, this batch file is used for synchronizing data between 2 folders
echo    a source and a destination folder, data^(files^|folders^) of the source 
echo    will be copied to the dest..
echo 2, a log file will be generated, and the log will show up when sync. is 
echo    done. any file changes, errors, ect. are recorded.
echo 3, a merging option is availabe, if activated, the dest. folder will be 
echo    maded completely the same as the source folder, it is very useful while  
echo    backuping^(both files and direcory structure, surely, some data of dest. 
echo    may be deleted^).
echo 4, if merging option is not activated(just copy new files to the 
echo    destination), run this bat onece, then swap the source and dest., run 
echo    again, which can make each of the 2 folders get what it do not have of 
echo    the other before sync., it is very useful while sync. 2 folders, say, 
echo    music files between your mobile devices and computer.
echo 5, to learn more about this batch file, read the comments and the code of 
echo    it. you may find more ways to use it.
echo 6, the author does not take any responsibility for the ueser's data loss, 
echo    tests are recommended before you first using it to sync..
echo 7, contact the author: gavineaglechou#gmail.com^(plz. replace ^# with ^@^).
echo.
echo syntax: sync_data ["srcPath" "dstPath" [1^|0] [y] [excludelist]]^|[?]
echo.
echo srcPath:      the source to be synced or backuped
echo dstPath:      the destination folder
echo 1^|0:          merge the destinaiton folder or not
echo y:            surpress the confirmation
echo excluldelist: files or folders to be exlcuded
echo ?:            show this help msg.
echo.
echo e.g1
echo sync_data "e:\videos" "k:\backup\videos" 1 y "e:\videos\sports"+"e:\videos\guitar\tutorial.flv"
echo files in "e:\videos" will be copyed to "k:\backup\videos" then the folder 
echo "k:\backup\videos" will be merged, the folder "e:\videos\sports" and the 
echo file "e:\videos\guitar\tutorial.flv" won't be copied
echo.
echo e.g2
echo sync_data
echo run this bat file and input information sequently
echo.
echo e.g3
echo sync_data "e:\videos" "k:\backup\videos" 0 y
echo files in "e:\videos" will be copyed to "k:\backup\videos" then the folder 
echo "k:\backup\videos" will be merged, no excluded list
echo.
echo e.g4
echo sync_data "e:\videos" "k:\backup\videos" 0
echo files in "e:\videos" will be copyed to "k:\backup\videos" and the folder 
echo "k:\backup\videos" won't merged, a confirm msg will showw up no excluded list
echo.
echo press any key to continue...
pause>nul
shift /1 & shift /1 & shift /1 & shift /1
goto start
exit
(版权所有,转载请注明)



2011年11月

(版权所有,转载请注明)


  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值