|
马上注册,结识高手,享用更多资源,轻松玩转三维网社区。
您需要 登录 才可以下载或查看,没有帐号?注册
x
批处理特殊符号的作用
3 V. |7 _3 D* U, M4 N9 _0 s: t% Z5 u: _2 o
. T- {% m u' [
1、%是个ESCAPE字符,通常将之译为转义字符,但也有更形象的译名脱逸字符、逃逸字符等。也就是说%不仅仅将与其相关的特定字符串转义并替换为特定字符串,而且自身也会被“脱逸”。而且类似于C语言中的转义字符"\",双%会转义并脱逸为单%,四%则脱为双%。
7 C G+ G9 |2 |3 ?. Q6 o) C+ T3 ?
# u2 K% ?: H* A. j9 Z' X1 n+ \ 2、for本身是一个特殊的命令,类似于一个特化的命令解释器,因为它的功能实现需要执行多条语句,因此它必须也具有对命令行(特指do后的命令行)分析处理的功能。而command/cmd实现for时自然会借用自身原有的命令行分析模块,因此for具有二级转义的特性,for中do后的语句被分两级分析和解释,第一级在command/cmd读入并解释for命令行时,第二级在for读入并解释do命令时,它通常会对同一命令行的进行多次解释。
! p$ q. {$ ~* ]$ a b+ Y# P# m
& S9 v7 z/ F. Y8 c0 ] 然后,我们可以注意到,在do中使用命令行参数变量和环境变量时,不需要双%,那是因为,这些变量在经过第一级转义后,被替换成特定的不变的字符串常量,参与for循环的所有执行过程;而替代变量则要求在执行(do后的子命令行中)过程中不断的动态变化,而这个变化自然仍需要通过脱逸字符来实现,因此使用双%就是成了必然的选择。4 h5 p, w/ y8 ?
+ M) r( O. r6 Z. ]; M* H# t
另外,还需要注意到,在命令行中使用for时不需要双%,这源于命令解释器对命令行与批处理的处理方式不同。在早期的DOS版本中,%在命令行中不被视为转义字符,所以不会被转义和脱逸,所以当时无法在命令行直接引用环境变量。而使用for时,只需要一个%供for进行转义和脱逸就够了。在以后的命令解释器版本中,加入了命令行转义的支持(主要是环境变量的支持),但命令行for使用单%的传统仍然保留了下来。
& i6 w5 a% ^/ x% F/ d) c& {+ A& @+ P# v) r& N& d7 C9 R/ S
而 cmd中的变量延迟替换是属于特殊的情况,但不违背以上的转义原则,只是for中的环境变量不再是常量了。$ f" K7 Y/ n. M0 Y! W1 A. C
, p$ S: X# S. L8 [5 [
, W: `. I- K& {! M5 ~, frmdir /S /Q %mhnet% 2>NUL 1>NUL 做简单解释- M& v( a3 W) [/ j/ b- k. ]9 w
$ @, R$ i( u) g# Q6 Y# n
; D$ d2 ^% Q0 `# Z$ Q7 i这句代码的大意是指将 %mhnet% 指定的目录删除,/s 代表删除其中的子目录, /q 表示删除目录树时不提示确认, 1>nul 表示将正确删除目录树的信息禁止输出,2>nul 表示将删除过程中的错误信息禁止输出
5 ~5 i% t- z1 i# A' G# ^+ [. p5 s. m6 s: j; k% K
其中的1与2都是代表某个数据流输入输出的地址(NT CMD 称之为句柄,MSDOS称之为设备),下表(引自WinXP帮助文档“使用命令重定向操作符 (Redirection Operators”一节))将列出可用的句柄。- X3 k. ~' L2 _$ m
$ _" P' l9 W: G+ p/ @9 W% N, s2 b& i% Y. C+ A$ D% l0 L' A8 a
句柄 句柄的数字代号 说明 4 r( _2 ~. M7 ?/ }8 K
STDIN 0 键盘输入 6 \6 J `) w- ^; y' Y, e) b
STDOUT 1 输出到命令提示符窗口
; H; x4 b. D8 \% z0 ySTDERR 2 错误输出到命令提示符窗口 , ^5 R1 H! r3 f. g4 u# a: j4 \
UNDEFINED 3-9 这些句柄由应用程序和各个具体工具单独定义
; n+ ]& H( \! `& h1 Y- W
/ G! [ a: W2 V! B0 M# w$ J: B9 V0 键盘输入 4 O# x5 B' P/ h) s
1 输出到命令提示符窗口
6 e$ _3 H6 h* z. l2 错误输出到命令提示符窗口
; G4 @; U. G: t3 j3-9 这些句柄由应用程序和各个具体工具单独定义。 . _8 ]* I x8 m/ [) {4 D
2 > nul 表示程序出错的信息也不显示。
( c3 b1 o! e* K( L+ e) mcall attrib -r -h c:\autoexec.bat >nul, o$ n6 Y5 g& u4 j# h4 A
这句其实是:
4 I) Z7 N$ R) X+ Lcall attrib -r -h c:\autoexec.bat 1 > nul5 E' f; M j& Z$ Q
这些1,2,0等等都是句柄,说白了就是代号,你只要知道1是代表输出信息,2是代表出错信息,0是代表键盘输入就行了。, g; c3 `2 w: m& X9 b
如果有什么不明白的可以多看看帮助与支持。
4 o5 L4 l3 B8 B" y9 \/ ?9 }( t7 ^* T c6 H4 O) r
例如:" M, L( y. l" D' J
屏蔽正常提示信息 del . 1>nul (或者del . >nul)
" N1 v/ b- X7 C; T3 w. _* D- H7 X屏蔽出错提示信息 del . 2>nul9 g/ g" d! w+ o
如果两种信息都要屏蔽 del . 1>nul 2>nul
' ~9 E+ z6 w4 p1 W9 C
& e( A. d0 Q* T/ [7 Y3 k0 R# X' Z8 H' L9 L' P' i5 a6 a- s
: e2 ?8 k/ {3 p, \% F( j: E命令行对重定向符号出现的位置不做过多限定,只要重定向符号后紧随“字符设备”即可,故以下语句等效:4 u ]2 A: b2 j N. u
7 [- t8 R* l5 X3 x& _8 k echo Hello World> hello.txt4 |# C$ |! s }0 P9 b, W3 ~
echo Hello> Hello.txt World
' {4 ^6 U8 |* n H3 K echo> Hello.txt Hello World0 H: k- u8 O! d& f) o, A
> hello.txt echo Hello World
4 |* r0 M' x0 i3 B3 @( h& J" D* ^8 a4 }" {
在NT系列命令行中,重定向的作用范围由整个命令行转变为单个命令语句,受到了命令分隔符&,&&,||和语句块的制约限制。 w3 Y7 P1 E2 f, e3 W9 |+ W
, V' f/ N' f1 Q7 |" U echo Message1> msg1.txt & echo Message2> msg2.txt
5 H' V! g$ i, s1 Y9 O if "%target%"=="" (echo message to screen ) else (echo message to file> %target%)
2 a d* V @. d7 i- t: o, w # V" U/ K2 r2 `& b; u& U) k
综上所述,>nul 意为将此句命令所产生的标准输出请求重新定向到空设备中,而因为此设备的缄默特性,即相当于将此语句的输出信息屏蔽(并非隐藏);而 2>nul 则是将程序执行错误时的标准错误信息输出请求重定向后屏蔽。它们联合使用,即为将此语句所可能产生的所有输出信息屏蔽。
3 {$ b8 D, N* K: N% K" \$ h1 Q, y3 k/ Z8 ]* ?- H0 D
7 R( w; J: j1 X2 V" e
“重定向”是MSDOS起就存在的命令行特性,负责将指定命令或语句所产生的输入输出请求由缺省的“控制台”转交给其它的“设备”来完成,它的启动标志是“重定向符号”(包括“>,>>,<”三个,其各自意义见[1])出现在句中。3 Z1 E7 |* V2 U ]$ o% _( y
) i1 h! q, x$ i& v' r 一般的命令行程序输入输出请求都通过内部定义三个“端口”(在NT下称为“句柄”,在DOS下未定义)来完成,分别为标准输入stdin、标准输出stdout、标准错误stderr。它们通常指向的设备为控制台(console,代码为CON),其中stdin指向控制台的键盘,stdout/stderr指向控制台的监视器。因此,控制台通常即指键盘与监视器的联合体,这是在早期大型机的终端机上所体现出来的概念。其中的stdin可被<重定向,stdout可被>、>>重定向,而stderr在DOS下不可直接重定向,只有通过ctty或其它命令将系统控制权转交给其它设备的方式,来间接完成。/ q$ I7 c& ?$ l! M* x
& c4 P7 q& i h( b/ f “设备”是指可控制PC硬件或端口的设备驱动程序或端口代码,它通常由系统底层或硬件驱动程序实现和支持。比如IO.SYS实现的控制台CON、系统时钟CLOCK$、未知设备CONFIG$、第一串口AUX、第一并口PRN、所有串口COM1~COM4、所有并口LPT1~LPT3、可用盘符A:-X:以及上文提到的空设备NUL。还有许多其它设备,比如HIMEM.SYS实现的XMSXXXX0,EMM386.EXE实现的EMMXXXX0,IFSHLP.SYS实现的IFS$HLP$等。
4 m1 b; U' J" F' K/ j1 M- t ( S& k$ O, C* G
在这些设备中,可以处理输入输出信息的很少,只有CON、NUL以及连接有输入输出硬件(打印机、MODEM等)的串口或并口设备。它们被称为“字符设备”,而磁盘文件也作为一种特殊的字符设备列选其中,这就大大扩充了重定向的自由度与实用性,以致很多人也将重定向称为“文件重定向”。5 _$ Q/ s1 W, [' O
0 k) |+ j) n. ^7 i* N2 `
空设备NUL是一个特殊的设备,因为它没有可控制的PC硬件或端口,而只是一个虚构的的设备或端口,它仅存在于软件层面。正因为如此,它可以接受所有重定向的输入输出请求而不给出任何回应(在NT下不会给出任何输入信息而结束输入请求,在DOS下则反复填充127个字节0后终止响应),这种特性使它很像天文学上的能吞噬一切物质和信息的“黑洞”,也很类似哲学上能颠转阴阳无中生有的“玄玄之道”。它之所以存在,是因为我们需要一个可以默默无闻地无条件吸纳各种冗余输出信息或输入请求的“回收站”,正如“黑洞”就像一个巨大的“宇宙垃圾场”一样( f/ M d2 |& y/ X# M
2 b$ `2 a; F, ?7 B
* \ a6 ?, d8 \
6 @+ \( ]. r1 S c/ F; e; w; b9 nCMD没有神经错乱,是set处理的整数太大了,set使用双字节存储整数,有32位的存贮范围限制,也就是说它的处理范围是2^-31~2^31-1,你的磁盘空间超过了这个范围溢出了。. q: e: _" W, u9 }6 P( I# e
. z$ f5 L k: W& K
对此我没有太好的解决办法,只有舍弃后三位后除以1049的近似算法。
& `4 O. }6 J' L+ `( x3 x. b' u6 U/ j( h7 Z4 D/ K
for /f "tokens=3" %%a in ('dir /-c c:\^|find "可用字节"') do set freesize=%%a( C2 E; J2 {; _0 Y5 t
set /a freesize=%freesize:~0,-3%/1049>nul! Z1 G+ t- G( p5 z: {
echo Freesize:%freesize%
# P) M" ?4 I, X
0 l" V0 o9 Q. }# f
1 G. h9 ^! V) `( h2 L
6 h, h( G! }8 ?9 k" q> 创建一个文件
4 S+ E$ E2 q) T5 a>> 追加到一个文件后面
7 n- Z8 W4 N8 u+ F4 q@ 前缀字符.表示执行时本行在cmd里面不显示, 可以使用 echo off关闭显示 % @! _( \3 G5 F( D0 J+ \( n
^ 对特殊符号( > < &)的前导字符. 第一个只是显示aaa 第二个输出文件bbb
- t( M& m/ @; b3 H; Hecho 123456 ^> aaa x+ C- f/ Y& X4 z/ l7 ?
echo 1231231 > bbb
$ G, V2 \* y* {() 包含命令 ( d! w( k& d1 n: [9 q/ O
(echo aa & echo bb) ( n% Z* U, e! y+ t8 D
, 和空格一样的缺省分隔符号.
7 `8 s) ]* `- o; 注释,表示后面为注释 / }; n/ H5 p% C! I' W8 L! d8 }
: 标号作用
1 Z$ C* w+ k4 n/ C3 ~6 E│ 管道操作
3 }2 \7 s W& T$ Y" D; 符号当命令相同的时候可以将不同的目标用;隔离开来但执行效果不变。如执行过程中发生错误则只返回错误报告但程序还是会继续执行
^ e. H( q( N1 X4 Q4 A) {- f: \+ B- K
首先, @ 不是一个命令, 而是DOS 批处理的一个特殊标记符, 仅用于屏蔽命令行回显. 下面是DOS命令行或批处理中可能会见到的一些特殊标记符:- D3 Z2 F" t# w8 f. ?2 C( V
CR(0D) 命令行结束符
& o5 Y( i T1 J1 rEscape(1B) ANSI转义字符引导符& c1 T! G" T" a2 M$ E
Space(20) 常用的参数界定符
* G$ G& r2 c7 j* fTab(09) ; = 不常用的参数界定符
+ M$ K0 x7 d. `$ L4 _1 e( a+ COPY命令文件连接符6 M, c/ s0 U# |: F
* ? 文件通配符
8 ~$ M3 h& X( Y3 b' o3 Z"" 字符串界定符
7 D- _' e6 J3 S" J9 S4 G| 命令管道符
, w0 T; c) s9 r }# B7 ^< > >> 文件重定向符
6 a1 M' k0 a1 g& h5 |@ 命令行回显屏蔽符8 ?2 a) _ c) W; |$ u+ u; M4 }
/ 参数开关引导符/ K c) m7 |2 m8 g% s7 ]$ Q
: 批处理标签引导符
& W# s! y6 R! w3 o& L% 批处理变量引导符
: }' B- n2 ?$ `/ O/ m: w$ K1 ?8 H6 }+ P* Q4 N% C8 V( T
" B, p0 K* H* F1 K* j其次, :: 确实可以起到rem 的注释作用, 而且更简洁有效; 但有两点需要注意:
3 r; V6 s, p$ [1 l( n g第一, 除了 :: 之外, 任何以 :开头的字符行, 在批处理中都被视作标号, 而直接忽略其后的所有内容, 只是为了与正常的标号相区别, 建议使用 goto 所无法识别的标号, 即在 :后紧跟一个非字母数字的一个特殊符号.
9 X5 z" V, h' }9 A; o5 D) G第二, 与rem 不同的是, ::后的字符行在执行时不会回显, 无论是否用echo on打开命令行回显状态, 因为命令解释器不认为他是一个有效的命令行, 就此点来看, rem 在某些场合下将比 :: 更为适用; 另外, rem 可以用于 config.sys 文件中.
: A7 z M4 ?; c P/ Y2 c% H) M' T; K7 N8 p
/ ?9 z$ v5 I9 D, I/ U5 {/ F- O. @
8 I! D) P: N0 s也可以使用以下的用法:
# X+ j7 r6 K9 u- t9 g/ U5 ^' bif exist command, e9 }8 }6 Q. v8 E, ]# H
device 是指DOS系统中已加载的设备, 在win98下通常有:1 e; w+ A+ v2 P0 c
AUX, PRN, CON, NUL' u3 o( \) i1 Q' L4 S8 E
COM1, COM2, COM3, COM4
& y* r, {4 z$ P' K" t7 y$ ULPT1, LPT2, LPT3, LPT4
3 m% K0 l6 [5 n1 v" R) ?XMSXXXX0, EMMXXXX0
- G9 F* P+ S) U) tA: B: C: ...,
/ ?" h3 G$ I e# X# O, n% F3 [CLOCK$, CONFIG$, DblBuff$, IFS$HLP$
0 j# h& M8 W, K% _/ ~具体的内容会因硬软件环境的不同而略有差异, 使用这些设备名称时, 需要保证以下三点:: h6 t2 g& s- a5 [! ^
1. 该设备确实存在(由软件虚拟的设备除外)
. k5 t/ z! Z& g+ i' j/ B2. 该设备驱动程序已加载(aux, prn等标准设备由系统缺省定义)
, @& S! m2 q0 b" ?0 k( U3. 该设备已准备好(主要是指a: b: ..., com1..., lpt1...等)
7 T: R* P- K! J) ^ ~4 Z- u' s可通过命令 mem/d | find "device" /i 来检阅你的系统中所加载的设备9 j0 E6 [8 J: u, S/ K" r
另外, 在DOS系统中, 设备也被认为是一种特殊的文件, 而文件也可以称作字符设备; 因为设备(device)与文件都是使用句柄(handle)来管理的, 句柄就是名字, 类似于文件名, 只不过句柄不是应用于磁盘管理, 而是应用于内存管理而已, 所谓设备加载也即指在内存中为其分配可引用的句柄.
7 \9 I$ B4 u" c; X' H
5 e4 B' f V' k3 N+ I* _& a2 Z" j一、>与>>3 G8 ^: p4 s4 c& \4 ^
1、>
* n+ W( m: u) g) d3 e# j: j' f9 B$ B 符号>的意思是传递并覆盖。他所起的作用是将运行后的回显结果传递到后面的范围(后面可是文件也可是默认的系统控制台)2 }3 b9 B/ E8 C5 ]4 V" a; h
* M b$ }1 ?7 }
例:
6 U$ X8 {2 j. N k8 Q@echo off
+ b4 k/ J+ \' D" T' H5 O1 y( }; \echo 英雄是好男人!> hero.txt
' D( |" D" n# j. l7 _. j% Mpause
' J6 x- Y, \: m/ C% t5 E8 U0 p6 B1 a) o
解说:这个程序是将“英雄是好男人!”传递到文件hero.txt中,如果原来hero.txt中有内容将被覆盖掉,也就是说无论你运行这个程序多少次,hero.txt中的内容始终是“英雄是好男人!”。' ?1 W: Y5 _9 g
, k# C7 d$ P( ~+ u
2、>>5 c( F, J0 D0 U2 w0 I* m+ M
符号>>的作用与符号>相似,但他们的区别在于>>是传递并在文件末尾追加>>也可将回显传递给控制台(用 法同上)( y6 w5 ?- X$ s& T5 i9 x/ T& R
* L+ v$ H& l4 H. ~6 s 例:仍然用上面的例子
$ z4 C, {; m: D@echo off
+ {- @0 n9 e4 `8 }8 ]! S" Z' Techo 英雄是好男人!>> hero.txt
# E/ f- _9 c$ s" m$ s2 D- S: Ppause
2 C/ [+ }2 B# a4 z
) y; V& {' `/ [8 i9 [5 \解说:这个程序仍是将“英雄是好男人!”传递到文件hero.txt中,但它是在行尾追加的,如果原来hero.txt中有内容将不会被覆盖掉,也就是说你运行这个程序n次,hero.txt中的内容会是n个“英雄是好男人!”。
: m" p; [* x) c k- y: P8 e& y0 a! h- e3 y4 z
二、&与&&& l9 d/ h& i" u- x
&符号允许在一行中使用2个以上不同的命令,当第一个命令执行失败将不影响第2个命令的执行。
) \# g/ X9 f. G5 t
/ D7 K \! i; [4 A &&符号也是允许在一行中使用2个以上不同的命令,当第一个命令执行失败后后续的命令将不会再被执行。
& J& k* y* Z8 S, |+ O4 r4 t
$ T6 K5 j9 n$ l; e( u3 p" }" V三、|, p, v5 _5 A9 G" y5 z+ W' b+ {
符号|是一个管道传输命令意思是将上一命令执行的结果传递给下一命令去处理。' D" n: f6 }3 }, p+ q1 U- `$ B# W
# y, B' t+ b+ }) p四、::
& c$ M8 J' {& t p! y+ c& \3 f 表示后面的语句是注释。相当于c++中的"//" 。' b9 @+ m3 a& N) `+ y# l0 Y
S1 {* h' V# {4 B五、@
/ ~7 D: G! u' L( E8 ~ 不显示@后面的命令。就是在程序运行时不让用户在屏幕上看见@后面的这条命令。+ S% S e% H5 p6 {& M- _
% o6 R6 q* [& t, K# L1 s$ \
六、 ^6 b8 \$ P( K2 J i5 K# c9 y( i4 e
符号^ 是对特殊符号 > 、<、 &、的前导字符。在命令中他将以上的3个符号的特殊动能去掉仅仅只吧他们 当成符号而不使用他们的特殊意义。
; x5 Y1 E; ~8 ^" O 例:
# k! W7 D' a& y+ i6 q: ^c:\>echo test ^> 1.txt
5 W3 v1 T/ A( j$ l" Xtest > 1.txt' w: N" [; z6 B- p# k
从上面可以看出并没有把test写入文件1.txt而是将test >1.txt 当字符串显示了出来。 |
|