bat批处理文件的相关命令

发布时间:2021-11-30 10:15:41

















Bat批处理文件??







1.? 批处理脚本



批处理脚本就是把一个一个的命令外加一些逻辑控制组合在一起使其可一次都被执行的文本文件。在Linux上为Shell脚本,而在Windows上则为bat脚本。Windows下脚本命令能够执行需要同时满足以下两个条件:


  1. 路径
    • 使用以驱动盘符开始的绝对路径,如c:a.bat
    • 使用从当前目录开始的相对路径,比如 b.bat或者..a..bat
    • 在系统环境变量PATH中指定的某一个目录下,比如%PATH%中包含c:a时,可以在命令行上直接执行b.bat
    • 可执行


后缀是.bat/cmd/com/exe的文件


批处理文件一般需要在命令行下执行,其中95/98下的命令行叫做MS-DOS命令行,而NT系的命令行才叫命令行终端


2.?
变量的声明和赋值(set 和=)


批处理脚本的环境变量有延迟解析的问题,即环境变量是在这一行开始执行前就已经被替换掉了的。

可以通过【cmd.exe /v:on】或者【setlocal ENABLEDELAYEDEXPANSION】来避免该问题,或者将块处理中的代码函数化(函数中就不能再使用语句块和setlocal了--针对对象变量)


当使用call a.bat执行完a.bat之后,在a.bat(没有使用setlocal)中使用set命令设置过的变量,在当前脚本中还能够继续被使用,且其值为a.bat中设置过的值




set 变量名=值? 如果等号(=)前后有空格的话,那么空格也作为变量名或者值的一部分了


set /a 变量名=算术表达式? 计算算术表达式的值,并将将其赋给变量,如【set /a test= %test% * 2】


set /p 变量名=提示信息? 这时提示信息会被提示给用户,并等待用户的输入,输入的内容赋值给变量


set 变量名=%
变量名
%值? 在变量末尾追加”值“


set 变量名=
? 删除变量


set? 所有变量的一览


set 变量前缀? 所有以变量前缀开头的变量的一览


setlocal/endlocal?局部环境变量的声明,即使没有用endlocal,在批处理脚本结束的时候也会隐含的调用endlocal




一些特殊的环境变量:


变量 内容 UNIX相当
%ERRORLEVEL% 刚刚执行完的命令或者函数的返回值 $?
%0 执行的命令名 $0
%1?%2 … %9 命令或者函数执行时所传递的参数 $1?$2 …
可以使用shift命令参数移位
%* 命令或者函数执行是所传递的所有参数 $*?$@
%CMDEXTVERSION% cmd命令的版本号 ?
%CMDCMDLINE% cmd命令启动时候的参数 ?
%PATH% 命令的搜索路径 $PATH
$LD_LIBRARY_PATH
%CD% 命令执行的当前路径,注意不是命令的路径 pwd命令,$PWD
%DATE% 当前日期 `date?+%Y/%m/%d`
%TIME% 当前时刻 `date?+%H/%M/%S`
%RANDOM% 随机数(0~32767) ?
%PATHEXT% 省略后缀的情况下可以执行的文件
通过ftype /?可以查看详情
?
%OS% OS名 ?
%USERNAME% 当前登录的用户名 $USER
%COMPUTERNAME% 机器的计算机名 ?
%HOMEDRIVE%
%HOMEPATH%
用户的家目录和驱动盘符 $HOME
%TEMP%
%TMP%
临时目录 ?




3.?
流程控制


1). if / else条件判断????





?序号 命令例子? 说明
1 if [not] exist 文件名 ( 命令1 ) [else 命令2] 判断文件是否存在
2 if [not] [/i] 字符串1 == 字符串2 ( 命令1 ) [else 命令2] 判断两个字符串是否相等
如果两边都是数字的话,作为数字进行比较
其他情况下作为字符串进行比较
3 if [/i] 字符串1 比较操作符 字符串2 ( 命令1 ) [else 命令2] 使用字符串操作符比较两个字符串
4 if [not] errorlevel 错误码 ( 命令1 ) [else 命令2] 判断上一个命令的退出码是否大于等于某一个值
5 if cmdextversion 版本号 ( 命令1 ) [else 命令2] 判断命令【cmd.exe】的内部版本号是否大于等于指定版本号
6 if defined 变量 ( 命令1 ) [else 命令2] 判断指定的变量是否存在
???

注意:



1. 命令1/命令2 必须要使用()括起来,当要执行多个命令的时候也必须使用()括起来

2. 在判断的==两边,尽量使用{}而不是使用"",因为如果%1中含有"的时候,该判断会出错

3. 在字符串比较的时候,【/i】表示比较的字符串不区分大小写。

4. if和else必须在同一行,或者if和最初的(在同一行,)和else在同一行,else后面必须有空格



IF {%1}=={%2} (



echo
?eq l.



) ELSE (



echo
?not eq l.



)









5. 因为没有相当于and 和or这样的操作符,所以不能进行复杂的运算

6. 可以使用的比较操作符如下



?序号 操作符? ?说明
1 ?EQU ?等于/相等
2 NEQ 不等于/不相等
3 LSS 小于
4 LEQ 小于等于
5 GTR 大于
6 GEQ 大于等于
???




2).? for循环



?序号 ?使用例子 ?说明
1 for %变量 in? (集合)? do 命令 [命令行参数] 仅对集合中的文件进行循环,不包含目录。即使是以正则表达式的方式指定
2 for /d %变量 in? (集合)? do 命令 [命令行参数] 当使用通配符(如?和*)时,仅对集合中匹配的目录进行循环
3 for /r [[盘符:]路径] %变量 in (集合) ? do 命令 [命令行参数] 以递归的方式对子目录也进行循环
4 for /l %变量 in (开始, 增量, 结束) ? do 命令 [命令行参数] 从开始到结束以增量的方式循环执行
5 ?for /f ["选项"]? %变量 in? (文件集合)? do 命令 [命令行参数] 对指定的文件中的各行进行循环
其中空行会被忽略掉
%变量指每一行中的第一个字段
6 ?for /f ["选项"]? %变量 in? (“字符串”)? do 命令 [命令行参数] 对字符串进行循环
%变量指每一行中的第一个字段
7 ?for /f ["选项"]? %变量 in? (‘命令行’)? do 命令 [命令行参数] 对命令行的输出结果中的各行进行循环,但仅限于标准输出中的各行
%变量指每一行中的第一个字段
8 for /f "usebackq[,选项]"? %变量 in? (“文件名”)? do 命令 [命令行参数] 对指定的文件中的各行进行循环
其中空行会被忽略掉。
%变量指每一行中的第一个字段
同5,但可以指定带有空格的文件名
9 for /f "usebackq[,选项]"? %变量 in? (字符串‘)? do 命令 [命令行参数] 对字符串进行循环
%变量指每一行中的第一个字段
同6
10 for /f "usebackq[,选项]"? %变量 in? (?字符串?)? do 命令 [命令行参数] 对命令行的输出结果中的各行进行循环,但仅限于标准输出中的各行
%变量指每一行中的第一个字段
同7

注意:



1. 关于【%变量】,如果是在批处理文件中时,需要写成【&&变量】,在命令行时为【%变量】。其中变量

??? 可以为a~z或者A~Z之间的任意一个字母,但是该变量名区分大小写。

2. 集合中各个元素的分隔符可以使用逗号(,),空格,分号(;)中的任意一种,或者混合使用,因此像???

?? 【%CLASSPATH%】和【%*】这样的变量也可以指定在集合的位置。但是集合中的某个元素包含特殊

??? 字符,比如【(】或者【)】时,需要使用【^】对其进行转义,即写成【^)】的样子。

3. 如果想使用【@】来达到执行时命令行不被显示的目的的话,需要在for前面和do后面的命令前两两个地方

??? 都要加上【@】符号。

4. 在使用/f参数的时候,可以使用双引号指定一下选项。使用空格分隔可以指定多个选项。



?选项 使用例子 ?说明
?skip=行数 ? 指定从文件的开头开始忽略的行数?
eol=行尾字符 for /f "eol=;" %i in (";注释")? do echo %i 以指定字符开始的行会被作为注释而忽略掉。也可以理解为指定表示一行结束的字符
delims=分隔符字符集 for /f "delims=,;" %i in ("abc;def,ghi") do echo %i %j %k 默认的分隔符字符集为空格和tab,使用该选项可以变更分隔符字符集。
usebackq 例子见上面的8/9/10 改变在集合中指定的字符串的解释方法。默认不追加双引号的字符串会被认为是文件名。这样的话包含有空格的文件名将无法指定。
如果使用了该选项,则解释如下:
使用双引号括起来的解释为文件名
使用反引号括起来的解释为命令
使用单引号括起来的解释为字符串
tokens=字段1,字段2,字段m-n,* >for /f "tokens=2" %i in ("a b c") do @echo %i
b
>for /f "tokens=1,3" %i in ("a b c") do @echo %i %j
a c
>for /f "tokens=2-4" %i in ("a b c d e") do @echo %i %j %k
b c d
>for /f "tokens=1,*" %i in ("a b c d e") do @echo %i --- %j
a --- b c d e
>for /f "tokens=*" %i in ("a b c d e") do @echo %i
a b c d e
指定从第几个字段开始赋值给变量,以及取出那些字段。【字段m-n】表示取第m到第n个字段。【*】表示指定的最后一个字段以后剩下的所有字段。
默认为从第一个字段开始赋值给【%变量】。后面的字段会自动的赋值给指定变量名的下一个字母的变量。比如变量指定为【%i】,那么第二个字段会被自动的赋值给【%j】。



3). goto语句和标签



if %~1 == abc goto match


echo 不一致


goto :EOF




:match


echo 一致



使用【:字符串】来声明一个标签,然后使用【goto 标签】来跳到指定的标签出,实现处理的转移

但是EOF是bat脚本中默认的隐含标签,表示到该批处理文件的结尾。因为需要使用【goto?
:EOF】来表示。


4). switch语句



在批处理脚本中没有switch/case这样的语句,需要使用goto语句来模拟。(如下)

但是要注意,这并不能完全实现。比如不能实现others或者default的功能,

因为如果在goto后面指定一个不存在的标签时,在运行到那里的时候会报批处理脚本的错误。


set case=1


goto caseA_%case%


:caseA_1


??? echo case1


??? goto caseA_end


:caseA_2


??? echo case2


??? goto caseA_end


:caseA_end


5). 死循环




process_:start


echo do process


goto process_start



6). 函数



?定义 使用?
?:func_label
??? setlocal
??? ~
??? endlocal
exit /b 返回码
call :func_label
call: func_label 参数列表
echo %errorlevel%
?需要注意 延迟环境变量的问题,特别是使用for或者if的语句块时




7) pause 暂停语句,执行到pause语句后,会等待用户的指示,然后继续执行



C:Documents and Settingsuser>pause

请按任意键继续. . .





4.? 关于输入输出/重定向

(1) 标准输出重定向到文件中(新建一个文件,或者覆盖原有内容)



【格式】 command > filename?


【例子】 dir > out.txt?







(2) 标准输出追加到既存文件的末尾



【格式】 command >> filename?


【例子】 dir >> out.txt?






(3) 标准错误重定向到文件中(新建文件或者覆盖原文件内容)



【格式】 command 2> filename?


【例子】 dir nonexist.txt 2>stderr.txt?







(注)"2"和">"不能存在空格,否则的话2会被解释为命令的参数






(4) 标准输出和错误输出都重定向到文件中
(新建文件或者覆盖原文件内容)



【格式】 command > filename 2>&1?


【例子】 dir nonexist.txt > out.txt 2>&1?





(5) 标准输出和错误输出都重定向到NUL中,不进行显示



【格式】 command 2>NUL 1>NUL?


【例子】 dir nonexist.txt 2>NUL?
1>NUL




(6) 通过管道符来实现重定向,即将前一命令的标准输出作为后一命令的标准输入



【格式】 command1 |command2

【例子】 type aaa.txt | more


(7) 从文件中读取内容,作为一个命令的输入



【格式】 command1 < file

【例子】 more
如果是想要标准输入作为for命令的输入时,需要使用管道的形式(command | for语句),即需要借助一个从标准输入读取数据然后又原样输出到标准输出的命令,然后for命令以管道的形式使用那个命令的输出。无论是在脚本外还是脚本内,都需要这样做。如果直接使用文件作为for语句的标准输入时,将会得不到文件中的内容。但是使用管道的话,管道后面的do语句中就不能再使用call 标签的形式了,好像是管道后面被作为了另外一个脚本来处理




(8)? 从文件中或者命令行的输出中读取内容进行处理时,请使用for语句的/f选项,具体请参照流程控制中的for语句说明。



(9) 输出到标准输出



【格式】 echo 字符串?

【例子】 echo? aaaa
如果是输出空行可以使用【echo.】或者【echo]】



5. 脚本中命令/脚本/函数的执行