使用
命令 /?
可以查看使用帮助
参考链接:点击前往
更多参考:点击前往

1. pause

image.png
要显示其他提示语,可以这样用:
Echo 其他提示语 & pause > nul

2. echo

image.png

echo off

对于这条语句之后的命令,关闭命令回显(回显的意思是打印一遍命令,再执行命令)

echo on

对于这条语句之后的命令,开启命令回显。

@echo off

关闭当前命令的回显,即不会回显echo off
image.png

输出空行,即相当于输入一个回车

  1. 格式:ECHO.<br /> 值得注意的是命令行中的“.”要紧跟在ECHO后面中间不能有空格,否则“.”将被当作提示信息输出到屏幕。另外“.”可以用,:;”/[\]+等任一符号替代。<br /> 命令ECHO.输出的回车,经DOS管道转向可以作为其它命令的输入,比如echo.|time即相当于在TIME命令执行后给出一个回车。所以执行时系统会在显示当前时间后,自动返回到DOS提示符状态

关闭DOS命令提示符

  1. DOS提示符状态下键入ECHO OFF,能够关闭DOS提示符的显示使屏幕只留下光标,直至键入ECHO ON,提示符才会重新出现。

建立新文件或增加文件内容

格式:ECHO 文件内容>文件名
ECHO 文件内容>>文件名

使喇叭鸣响

C:>ECHO ^G
“^G”是在dos窗口中用Ctrl+G或Alt+007输入,输入多个^G可以产生多声鸣响。使用方法是直接将其加入批处理文件中或做成批处理文件调用。
这里的“^G”属于特殊符号的使用,

3. call

在批处理执行过程中调用另一个批处理,当另一个批处理执行完后,再继续执行原来的批处理
image.png
当路径中包含中文时,比如在test1.bat调用test2.bat,test2.bat的路径中包含中文,将test1.bat的文件转码成ANSI格式,当路径中包含空格时,需要用双引号括起来“路径”。
调用一条批处理命令,和直接执行命令效果一样,特殊情况下很有用,比如变量的多级嵌套,见教程后面。在批处理编程中,可以根据一定条件生成命令字符串,用call可以执行该字符串,见例子。
CALL [drive:][path]filename [batch-parameters]
调用的其它批处理程序。filename 参数必须具有 .bat 或 .cmd 扩展名。
CALL :label arguments
调用本文件内命令段,相当于子程序。被调用的命令段以标签:label开头,以命令goto :eof结尾。

  1. @echo off
  2. Echo 产生一个临时文件 > tmp.txt
  3. Rem 下行先保存当前目录,再将c:\windows设为当前目录
  4. pushd c:\windows
  5. Call :sub tmp.txt
  6. Rem 下行恢复前次的当前目录
  7. Popd
  8. Call :sub tmp.txt
  9. pause
  10. Del tmp.txt
  11. exit
  12. :sub
  13. Echo 删除引号: %~1
  14. Echo 扩充到路径: %~f1
  15. Echo 扩充到一个驱动器号: %~d1
  16. Echo 扩充到一个路径: %~p1
  17. Echo 扩充到一个文件名: %~n1
  18. Echo 扩充到一个文件扩展名: %~x1
  19. Echo 扩充的路径指含有短名: %~s1
  20. Echo 扩充到文件属性: %~a1
  21. Echo 扩充到文件的日期/时间: %~t1
  22. Echo 扩充到文件的大小: %~z1
  23. Echo 扩展到驱动器号和路径:%~dp1
  24. Echo 扩展到文件名和扩展名:%~nx1
  25. Echo 扩展到类似 DIR 的输出行:%~ftza1
  26. Echo.
  27. Goto :eof

image.png

4. chcp

image.png
当控制台显示中文乱码时,在bat文件的最上面声明
chcp 65001
代表使用utf8编码
936代表gbk编码

5. start

启动单独的“命令提示符”窗口来运行指定程序或命令。
image.png
image.png
image.png
例:start explorer d:\
调用图形界面打开D盘

6. %0-%9

%0是指批处理文件的本身,%1-%9是传入的参数。这个参数是从批处理外传入的。
image.png

7. choice

使用此命令可以让用户输入一个字符,从而运行不同的命令。
输入/?指令查看指令详情
image.png

  1. @echo off
  2. chcp 65001
  3. CHOICE /C YNC /M "确认请按 Y,否请按 N,或者取消请按 C。"
  4. CHOICE /T 10 /C ync /CS /D y
  5. CHOICE /C ab /M "选项 1 请选择 a,选项 2 请选择 b。"
  6. CHOICE /C ab /N /M "选项 1 请选择 a,选项 2 请选择 b。"

image.png

8. type

显示文件内容
image.png
image.png

9. set

该指令用来设置变量
set 变量名=
可以清除变量
image.png
image.png
image.png

  1. @echo off
  2. echo hello world
  3. ::不带参数为设置变量
  4. set value=123456
  5. echo 输入的值为%value%
  6. pause
  7. @echo off
  8. echo hello world
  9. :: set /p 变量=等待输入的提示字
  10. set /p value=请输入值:
  11. echo 输入的值为%value%
  12. pause
  13. @echo off
  14. echo hello world
  15. :: set /a 变量=公式
  16. set /a value=1+2+3
  17. echo 结果:%value%
  18. pause

image.png
详细使用参考:set命令使用

10. if

image.png
image.png

  1. IF [NOT] ERRORLEVEL number command
    IF ERRORLEVEL这个句子必须放在某一个命令的后面,执行命令后由IF ERRORLEVEL 来判断命令的返回值。Number的数字取值范围0~255,判断时值的排列顺序应该由大到小。返回的值大于等于指定的值时,条件成立.

    查看文件是否存在

    1. @echo off
    2. if exist exclude.txt (
    3. echo this file exist
    4. ) else (
    5. echo this file not exist)
    6. pause
    image.png
    image.png :::info 注意:else必须和if在同一行,或者和if最后的括号在同一行,如: ……) ELSE (……。在括号那换行程序认为是一条语句。 :::

    判断字符串是否相等

    为了防止字符串中含有空格,可用以下格式
    if [NOT] {string1}=={string2} command
    if [NOT] [string1]==[string2] command
    if [NOT] “string1”==”string2” command
    这种写法实际上将括号或引号当成字符串的一部分了,只要等号左右两边一致就行了,比如下面的写法就不行:
    if {string1}==[string2] command
    image.png
    image.png

    与choice一起使用

    image.png

    字符串对比

    image.png

    条件循环

    for命令循环有一个缺点,就是整个循环被当作一条命令语句,涉及到变量延迟的问题。
    利用goto语句和条件判断,dos可以实现条件循环,很简单啦,看例子:
    例:
    @echo off
    set var=0
    rem **循环开始了
    :continue
    set /a var+=1
    echo 第%var%次循环
    if %var% lss 100 goto continue
    rem **循环结束了
    echo 循环执行完毕
    pause

例:
@echo off
set var=100
rem **循环开始了
:continue
echo 第%var%次循环
set /a var-=1
if %var% gtr 0 goto continue
rem **循环结束了
echo 循环执行完毕
pause

11. for

image.png
image.png
image.png
循环指令。这里需要了解两个关键字%i%%i
%i这个关键字不能在bat中使用。只能再CMD命令下的for中使用。
例如在cmd中:for %i in(command1) do command2

%%i是在bat的for中使用的指令。
例如for %%i in(command1) do command2
for %%i in(command1) do command2是for的语法使用规则。

  1. for、in和do是for语句的关键字,它们三个缺一不可;
  2. %%I是for语句中对形式变量的引用,即使变量l在do后的语句中没有参与语句的执行,也是必须出现的;
  3. in之后,do之前的括号不能省略;
  4. command1表示字符串或变量,command2表示字符串、变量或命令语句;意思为:循环调用command1中的元素作为参数,来参与command2的执行。

此外需要注意几点

  1. for语句的形式变量I,可以换成26个字母中的任意一个,这些字母会区分大小写,也就是说,%%I和%%i会被认为不是同一个变量;形式变量I还可以换成其他的字符,但是,为了不与批处理中的%0~%9这10个形式变量发生冲突,请不要随意把%%I替换为%%0~%%9中的任意一个;
  2. in和do之间的command1表示的字符串或变量可以是一个,也可以是多个,每一个字符串或变量,我们称之为一个元素,每个元素之间,用空格键、跳格键、逗号、分号或等号分隔;
  3. for语句依次提取command1中的每一个元素,把它的值赋予形式变量I,带到do后的command2中参与命令的执行;并且每次只提取一个元素,然后执行一次do后的命令语句,而无论这个元素是否被带到command2中参与了command2的运行;当执行完一次do后的语句之后,再提取command1中的下一个元素,再执行一次command2,如此循环,直到command1中的所有元素都已经被提取完毕,该for语句才宣告执行结束。

image.png :::info for /l …. 表示以增量形式从开始到结束的一个数字序列 :::

高级用法

image.png

参数 /D

只返回目录名
FOR /D %%variable IN (set) DO command [command-parameters]
如果集中包含通配符,则指定与目录名匹配,而不与文件名匹配。
如果 Set (也就是我上面写的 “相关文件或命令”) 包含通配符( 和 ?),将对与 Set 相匹配的每个目录(而不是指定目录中的文件组)执行指定的 Command。
这个参数主要用于目录搜索,不会搜索文件,看这样的例子
@echo off
for /d %%i in (c:\
) do echo %%i
pause
运行会把C盘根目录下的全部目录名字打印出来,而文件名字一个也不显示!
在来一个,比如我们要把当前路径下文件夹的名字只有1-3个字母的打出来
@echo off
for /d %%i in (???) do echo %%i
pause
这样的话如果你当前目录下有目录名字只有1-3个字母的,就会显示出来,没有就不显示了
这里解释下号和?号的作用,号表示任意N个字符,而?号只表示任意一个字符
知道作用了,给大家个思考题目!
@echo off
for /d %%i in (window?) do echo %%i
pause
保存到C盘下执行,会显示什么呢?自己看吧! 显示:windows
/D参数只能显示当前目录下的目录名字,这个大家要注意!

参数 /R

递归
FOR /R [[drive:]path] %%variable IN (set) DO command [command-parameters]
检查以 [drive:]path 为根的目录树,指向每个目录中的FOR 语句。如果在 /R 后没有指定目录,则使用当前目录。如果集仅为一个单点(.)字符,则枚举该目录树。
1、set中的文件名如果含有通配符(?或),则列举/R参数指定的目录及其下面的所用子目录中与set相符合的所有文件,无相符文件的目录则不列举。
2、相反,如果set中为具体文件名,不含通配符,则枚举该目录树(即列举该目录及其下面的所有子目录),而不管set中的指定文件是否存在。这与前面所说的单点(.)枚举目录树是一个道理,单点代表当前目录,也可视为一个文件。
例:
@echo off
for /r c:\ %%i in (
.exe) do echo %%i
pause
咱们把这个BAT保存到D盘随便哪里然后执行,我会就会看到,他把C盘根目录,和每个目录的子目录下面全部的EXE文件都列出来了!!!!
例:
@echo off
for /r c:\ %%i in (boot.ini) do echo %%i
pause
运行本例发现枚举了c盘所有目录,为了只列举boot.ini存在的目录,可改成下面这样:
@echo off
for /r c:\ %%i in (boot.ini) do if exist %%i echo %%i
pause
用这条命令搜索文件真不错。。。。。。

参数 /L

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)。
使 用迭代变量设置起始值 (Start#),然后逐步执行一组范围的值,直到该值超过所设置的终止值 (End#)。/L 将通过对 Start# 与 End# 进行比较来执行迭代变量。如果 Start# 小于 End#,就会执行该命令。如果迭代变量超过 End#,则命令解释程序退出此循环。还可以使用负的 Step# 以递减数值的方式逐步执行此范围内的值。例如,(1,1,5) 生成序列 1 2 3 4 5,而 (5,-1,1) 则生成序列 (5 4 3 2 1)。语法是:
看着这说明有点晕吧!咱们看例子就不晕了!
@echo off
for /l %%i in (1,1,5) do @echo %%i
pause
保存执行看效果,他会打印从1 2 3 4 5 这样5个数字
(1,1,5)这个参数也就是表示从1开始每次加1直到5终止!
等会晕,就打印个数字有P用…好的满足大家,看这个例子
@echo off
for /l %%i in (1,1,5) do start cmd
pause
执行后是不是吓了一跳,怎么多了5个CMD窗口,呵呵!如果把那个 (1,1,5)改成 (1,1,65535)会有什么结果,我先告诉大家,会打开65535个CMD窗口….这么多你不死机算你强!
当然我们也可以把那个start cmd改成md %%i 这样就会建立指定个目录了!!!名字为1-65535

参数 /F

\迭代及文件解析
使用文件解析来处理命令输出、字符串及文件内容。使用迭代变量定义要检查的内容或字符串,并使用各种options选项进一步修改解析方式。使用options令牌选项指定哪些令牌应该作为迭代变量传递。请注意:在没有使用令牌选项时,/F 将只检查第一个令牌。
文件解析过程包括读取输出、字符串或文件内容,将其分成独立的文本行以及再将每行解析成零个或更多个令牌。然后通过设置为令牌的迭代变量值,调用 for 循环。默认情况下,/F 传递每个文件每一行的第一个空白分隔符号。跳过空行。

详细的帮助格式为:
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]
带引号的字符串”options”包括一个或多个
指定不同解析选项的关键字。这些关键字为:
eol=c - 指一个行注释字符的结尾(就一个)(备注:默认以使用;号为行首字符的为注释行)
skip=n - 指在文件开始时忽略的行数,(备注:最小为1,n可以大于文件的总行数,默认为1。)
delims=xxx - 指分隔符集。这个替换了空格和跳格键的默认分隔符集。
tokens=x,y,m-n - 指每行的哪一个符号被传递到每个迭代的 for 本身。这会导致额外变量名称的分配。m-n 格式为一个范围。通过 nth 符号指定 mth。如果符号字符串中的最后一个字符星号,那么额外的变量将在最后一个符号解析之后分配并接受行的保留文本。经测试,该参数最多只能区分31个字段。(备注:默认为1,则表示只显示分割后的第一列的内容,最大是31,超过最大则无法表示)
usebackq - 使用后引号(键盘上数字1左面的那个键)。<br /> 未使用参数usebackq时:file-set表示文件,但不能含有空格<br /> 双引号表示字符串,即"string"<br /> 单引号表示执行命令,即'command'<br /> 使用参数usebackq时:file-set和"file-set"都表示文件<br /> 当文件路径或名称中有空格时,就可以用双引号括起来<br /> 单引号表示字符串,即'string'<br /> 后引号表示命令执行,即command`

以上是用for /?命令获得的帮助信息,直接复制过来的,括号中的备注为我添加的说明。
晕惨了!我这就举个例子帮助大家来理解这些参数!

For命令例1:**
@echo off
rem 首先建立临时文件test.txt
echo ;注释行,这是临时文件,用完删除 >test.txt
echo 11段 12段 13段 14段 15段 16段 >>test.txt
echo 21段,22段,23段,24段,25段,26段 >>test.txt
echo 31段-32段-33段-34段-35段-36段 >>test.txt
FOR /F “eol=; tokens=1,3 delims=,- “ %%i in (test.txt) do echo %%i %%j %%k
Pause
Del test.txt
运行显示结果:
11段 13段 14段 15段 16段
21段 23段 24段,25段,26段
31段 33段 34段-35段-36段
请按任意键继续. . .
为什么会这样?我来解释:
eol=; 分号开头的行为注释行
tokens=1,3
将每行第1段,第3段和剩余字段分别赋予变量%%i,%%j,%%k
delims=,- (减号后有一空格)以逗号减号和空格为分隔符,空格必须放在最后

For命令例2:**
@echo off
FOR /F “eol= delims=” %%i in (test.txt) do echo %%i
Pause
运行将显示test.txt全部内容,包括注释行,不解释了哈。

For命令例3:**
另外/F参数还可以以输出命令的结果看这个例子
@echo off
FOR /F “delims=” %%i in (‘net user’) do @echo %%i
pause
这样你本机全部帐号名字就出来了把扩号内的内容用两个单引号引起来就表示那个当命令执行,FOR会返回命令的每行结果,加那个”delims=” 是为了让我空格的行能整行显示出来,不加就只显示空格左边一列!

变量

我们可以看到每行都有一个大写字母”I”,这个I其实就是我们在FOR带入的变量,我们FOR语句代入的变量名是什么,这里就写什么.
比如:FOR /F %%z IN (‘set’) DO @echo %%z
这里我们代入的变量名是z那么我们就要把那个I改成z,例如%~fI改为%~fz
至于前面的%~p这样的内容就是语法了!

~I - 删除任何引号(“),扩展 %I

这个变量的作用就如他的说明,删除引号!
我们来看这个例子:
首先建立临时文件temp.txt,内容如下
“1111
“2222”
3333”
“4444”44
“55”55”55
可建立个BAT文件代码如下:
@echo off
echo ^”1111>temp.txt
echo “2222”>>temp.txt
echo 3333^”>>temp.txt
echo “4444”44>>temp.txt
echo ^”55”55”55>>temp.txt
rem 上面建立临时文件,注意不成对的引号要加转义字符^,重定向符号前不要留空格
FOR /F “delims=” %%i IN (temp.txt) DO echo %%~i
pause
del temp.txt
执行后,我们看CMD的回显如下:
1111 #字符串前的引号被删除了
2222 #字符串首尾的引号都被删除了
3333” #字符串前无引号,后面的引号保留
4444”44 #字符串前面的引号删除了,而中间的引号保留
55”55”55 #字符串前面的引号删除了,而中间的引号保留
请按任意键继续. . .
和之前temp.txt中的内容对比一下,我们会发现第1、2、5行的引号都消失了,这就是删除引号~i的作用了!
删除引号规则如下(BAT兄补充!)
1、若字符串首尾同时存在引号,则删除首尾的引号;
2、若字符串尾不存在引号,则删除字符串首的引号;
3、如果字符串中间存在引号,或者只在尾部存在引号,则不删除。
龙卷风补充:无头不删,有头连尾删。

其他

image.png

12. goto

用于跳转
image.png
image.png

13. 符号(&、&&、||、|、>、>>)

@ 命令行回显屏蔽符

关闭当前行的回显。ECHO OFF可以关闭掉整个批处理命令的回显,但不能关掉ECHO OFF这个命令,现在我们在ECHO OFF这个命令前加个@,就可以达到所有命令均不回显的要求。

% 批处理变量引导符

这个百分号严格来说是算不上命令的,它只是批处理中的参数而已(多个%一起使用的情况除外,以后还将详细介绍)。
引用变量用%var%,调用程序外部参数用%1至%9等等
%0 %1 %2 %3 %4 %5 %6 %7 %8 %9 %为命令行传递给批处理的参数
%0 批处理文件本身,包括完整的路径和扩展名
%1 第一个参数
%9 第九个参数
%
从第一个参数开始的所有参数
参数%0具有特殊的功能,可以调用批处理自身,以达到批处理本身循环的目的,也可以复制文件自身等等。
小技巧:添加行内注释
%注释内容%(可以用作行内注释,不能出现重定向符号和管道符号)
为什么这样呢?此时“注释内容”其实被当作变量,其值是空的,故只起注释作用,不过这种用法容易出现语法错误,一般不用。

> 和 >>

输出重定向命令,DOS的标准输入输出通常是在标准设备键盘和显示器上进行的,利用重定向,可以方便地将输入输出改向磁盘文件或其它设备。其中:

  1. 大于号“>”将命令发送到文件或设备,例如打印机>prn。使用大于号“>”时,有些命令输出(例如错误消息)不能重定向。
  2. 双大于号“>>”将命令输出添加到文件结尾而不删除文件中已有的信息。
  3. 小于号“<”从文件而不是键盘上获取命令所需的输入。
  4. &符号将输出从一个默认I/O流(stdout,stdin,stderr)重新定向到另一个默认I/O流。

例如,command >output_file 2>&1将处理command过程中的所有错误信息从屏幕重定向到标准文件输出中。

句柄名称 说明
STDIN 0 标准输入,发送自键盘
STDUOT 1 标准输出,发送到命令Shell窗口
STDERR 2 标准错误输出,发送到命令Shell窗口
UNDEFINED 3~9 特定于应用程序的句柄

这个字符的意思是传递并且覆盖,他所起的作用是将运行的结果传递到后面的范围(后边可以是文件,也可以是默认的系统控制台)
在NT系列命令行中,重定向的作用范围由整个命令行转变为单个命令语句,受到了命令分隔符&,&&,||和语句块的制约限制。
比如:
使用命令:echo hello >1.txt将建立文件1.txt,内容为”hello “(注意行尾有一空格)
使用命令:echo hello>1.txt将建立文件1.txt,内容为”hello“(注意行尾没有空格):
详细使用参考:Linux 简易理解重定向以及 2>&1 的使用

| 管道符

格式:第一条命令 | 第二条命令 [| 第三条命令…]
将第一条命令的结果作为第二条命令的参数来使用

^ 转义符

^是对特殊符号<,>,&的前导字符,在命令中他将以上3个符号的特殊功能去掉,仅仅只把他们当成符号而不使用他们的特殊意义。比如
echo test ^>1.txt
结果则是:test > 1.txt
他没有追加在1.txt里,只是显示了出来
另外,此转义字符还可以用作续行符号。举个简单的例子:
image.png
为什么转义字符放在行尾可以起到续行符的作用呢?原因很简单,因为每行末尾还有一个看不见的符号,即回车符,转义字符位于行尾时就让回车符失效了,从而起到了续行的作用。

组合命令 & && ||

&、&&、||为组合命令,顾名思义,就是可以把多个命令组合起来当一个命令来执行。这在批处理脚本里是允许的,而且用的非常广泛。因为批处理认行不认命令数目。

&

语法:第一条命令 & 第二条命令 [& 第三条命令…]
& 这个符号允许在一行中使用2个以上不同的命令,当第一个命令执行失败了,也不影响后边的命令执行。

&&

语法:第一条命令 && 第二条命令 [&& 第三条命令…]
用这种方法可以同时执行多条命令,当碰到执行出错的命令后将不执行后面的命令,如果一直没有出错则一直执行完所有命令

||

语法:第一条命令 || 第二条命令 [|| 第三条命令…]
用这种方法可以同时执行多条命令,当一条命令失败后才执行第二条命令,当碰到执行正确的命令后将不执行后面的命令,如果没有出现正确的命令则一直执行完所有命令;
提示:组合命令和重定向命令一起使用必须注意优先级
管道命令的优先级高于重定向命令,重定向命令的优先级高于组合命令
问题:把C盘和D盘的文件和文件夹列出到a.txt文件中。
dir c:\ > a.txt && dir d:\ >> a.txt
或 dir c:\ > a.txt & dir d:\ >> a.txt
[这个也可以用 dir c:\;d:\ >>a.txt 来实现]

, 逗号

逗号相当于空格,在某些情况下“,”可以用来当做空格使 比如
dir,c:\

; 分号

分号,当命令相同时,可以将不同目标用;来隔离,但执行效果不变,如执行过程中发生错误,则只返回错误报告,但程序仍会执行。(有人说不会继续执行,其实测试一下就知道了,只不过它的执行有个规则,请看下面的规则)
比如:
dir c:\;d:\;e:\;z:\
以上命令相当于
dir c:\
dir d:\
dir e:\
dir f:\
如果其中z盘不存在,运行显示:系统找不到指定的路径。然后终止命令的执行。
例:dir c:\;d:\;e:\1.txt
以上命令相当于
dir c:\
dir d:\
dir e:\1.txt
其中文件e:\1.txt不存在,但e盘存在,有错误提示,但命令仍会执行。

规则:(我是在操作系统是XP SP3,英文版下测试的)
1.如果目标路径不存在,则整个语句都不执行,例如dir c:\;c:\dfdfdf\a.txt,则根本不会执行,因为我没有c:\dfdfdf\这个目录;
2.如果路径存在,仅文件不存在,则会继续执行,并且提示文件不存在的错误,例如:dir c:\;c:\temp\a.txt,我的目录中有c:\temp\文件夹,但这个目录下面没有1.txt这个文件。

() 括号

小括号在批处理编程中有特殊的作用,左右括号必须成对使用,括号中可以包括多行命令,这些命令将被看成一个整体,视为一条命令行。
括号在for语句和if语句中常见,用来嵌套使用循环或条件语句,其实括号()也可以单独使用,请看例子。
例:
命令:echo 1 & echo 2 & echo 3
可以写成:
(
echo 1
echo 2
echo 3
)
上面两种写法效果一样,这两种写法都被视为是一条命令行。
注意:这种多条命令被视为一条命令行时,如果其中有变量,就涉及到变量延迟的问题。

! 感叹号

在变量延迟问题中,用来表示变量,即%var%应该表示为!var!

14. 延迟环境变量扩展

  1. CMD在解释我们的命令的时候,首先会读取命令行一条完整的命令。然后对其进行一些命令格式的匹配操作,看你所输入的命令格式是不是符合他的要求。如果我们要在我们的命令中引用一些变量,那么我们如何让CMD在解释我们的命令时。能识别出这个变量呢?这时我们就可以在变量名字两边加一个%号, 如%name%。当CMD在对读取我们的整行命令进行格式匹配的时候,就会发现name这个字符两边加了%号,就不会把他当作普通字符处理,而是会把他当 作一个变量处理。变量名叫name。然后CMD就会找到变量名对应的值,用变量名的值替换掉这个变量名字(name),(如果变量名不存在值,就返回空 值)。再将这个替换好并且匹配的命令执行。这个替换值的过程就叫做变量扩展。说白了就是把变量的名字,用他的值给替换掉后执行。也就是批处理如何识别一 个变量的过程.。<br />![image.png](https://cdn.nlark.com/yuque/0/2022/png/21774943/1653405450464-45d266bd-23af-4b33-88ef-a50b04aadfc2.png#clientId=ucf7d5c71-c886-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=265&id=u980121ac&margin=%5Bobject%20Object%5D&name=image.png&originHeight=398&originWidth=781&originalType=binary&ratio=1&rotation=0&showTitle=false&size=47815&status=done&style=none&taskId=u4ca0241f-e0c1-46cf-99d5-0ff137c6e52&title=&width=520.6666666666666)<br />这个在预编译的时候将%var2%替换成%%i,但是%%i又不认识是什么,所以程序在运行的时候就会出错。<br />这时就需要使用延迟环境变量扩展,即每条指令在**执行之前才将变量进行替换**,以保证对变量的任何修改都可以实时生效.。<br />使用setloacl ENABLEDELAYEDEXPANSION这个命令来启用\"延迟环境变量扩展\",遇到的变量需要用!变量!进行替换。<br />代码修改之后重新运行<br />![image.png](https://cdn.nlark.com/yuque/0/2022/png/21774943/1653405766090-55ea74f6-00e8-48b7-b93e-aefd566ed423.png#clientId=ucf7d5c71-c886-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=236&id=u730d561d&margin=%5Bobject%20Object%5D&name=image.png&originHeight=354&originWidth=827&originalType=binary&ratio=1&rotation=0&showTitle=false&size=40323&status=done&style=none&taskId=u6b8815ae-b155-41ac-bbe7-63dee9ce9b2&title=&width=551.3333333333334)

:::info 提示:在没有开启变量延迟的情况下,某条命令行中的变量改变,必须到下一条命令才能体现。这一点也可以加以利用, ::: image.png

15. exit

退出当前控制台
image.png

  1. @echo off
  2. setlocal ENABLEDELAYEDEXPANSION
  3. for /l %%a in (0,0,0) do (
  4. set /p input=请输入:
  5. echo !input!
  6. if !input!==pass (exit))
  7. pause

image.png

16. errorlevel

程序返回码
echo %errorlevel%
每个命令运行结束,可以用这个命令行格式查看返回码,用于判断刚才的命令是否执行成功,默认值为0,一般命令执行出错会设 errorlevel 为1。

17. title

设置cmd窗口的标题
title 新标题 #可以看到cmd窗口的标题栏变了

18. color

image.png

19. mode

image.png
例:
mode con cols=113 lines=15 & color 9f
此命令设置DOS窗口大小:15行,113列 颜色为9f
image.png

20. 注释 REM 和 ::

REM为注释命令,一般用来给程序加上注解,该命令后的内容不被执行,但能回显。
其次, :: 也可以起到rem 的注释作用, 而且更简洁有效; 但有两点需要注意:
第一, 任何以冒号:开头的字符行, 在批处理中都被视作标号, 而直接忽略其后的所有内容。
有效标号:冒号后紧跟一个以字母数字开头的字符串,goto语句可以识别。
无效标号:冒号后紧跟一个非字母数字的一个特殊符号,goto无法识别的标号,可以起到注释作用,所以 :: 常被用作注释符号,其实 :+ 也可起注释作用。
第 二, 与rem 不同的是, ::后的字符行在执行时不会回显, 无论是否用echo on打开命令行回显状态, 因为命令解释器不认为他是一个有效的命令行, 就此点来看, rem 在某些场合下将比 :: 更为适用; 另外, rem 可以用于 config.sys 文件中。
行内注释格式:%注释内容% (不常用,慎用)
image.png

21. find

image.png
image.png

22. assoc和ftype

image.png
image.png
文件关联
assoc 设置’文件扩展名’关联,关联到’文件类型’
ftype 设置’文件类型’关联,关联到’执行程序和参数’
当你双击一个.txt文件时,windows并不是根据.txt直接判断用 notepad.exe 打开
而是先判断.txt属于 txtfile ‘文件类型’
再调用 txtfile 关联的命令行 txtfile=%SystemRoot%\system32\NOTEPAD.EXE %1
可以在”文件夹选项”→”文件类型”里修改这2种关联
assoc #显示所有’文件扩展名’关联
assoc .txt #显示.txt代表的’文件类型’,结果显示 .txt=txtfile
assoc .doc #显示.doc代表的’文件类型’,结果显示 .doc=Word.Document.8
assoc .exe #显示.exe代表的’文件类型’,结果显示 .exe=exefile
ftype #显示所有’文件类型’关联
ftype exefile #显示exefile类型关联的命令行,结果显示 exefile=”%1” %*
assoc .txt=Word.Document.8
设置.txt为word类型的文档,可以看到.txt文件的图标都变了
assoc .txt=txtfile
恢复.txt的正确关联

ftype exefile=”%1” %*
恢复 exefile 的正确关联
如果该关联已经被破坏,可以运行 command.com ,再输入这条命令

23. pushd和popd

切换当前目录
image.png
@echo off
c: & cd\ & md mp3 #在 C:\ 建立 mp3 文件夹
md d:\mp4 #在 D:\ 建立 mp4 文件夹
cd /d d:\mp4 #更改当前目录为 d:\mp4
pushd c:\mp3 #保存当前目录,并切换当前目录为 c:\mp3
popd #恢复当前目录为刚才保存的 d:\mp4
一般用处不大,在当前目录名不确定时,会有点帮助。(dos编程中很有用)

24. shift

image.png

25. attrib

image.png
例:
md autorun
attrib +a +s +h autorun
上面的命令将建立文件夹autorun,然后将其设为存档、系统、隐藏属性

26. 系统变量

%ALLUSERSPROFILE% 本地 返回“所有用户”配置文件的位置。
%APPDATA% 本地 返回默认情况下应用程序存储数据的位置。
%CD% 本地 返回当前目录字符串。
%CMDCMDLINE% 本地 返回用来启动当前的 Cmd.exe 的准确命令行。
%CMDEXTVERSION% 系统 返回当前的“命令处理程序扩展”的版本号。
%COMPUTERNAME% 系统 返回计算机的名称。
%COMSPEC% 系统 返回命令行解释器可执行程序的准确路径。
%DATE% 系统 返回当前日期。使用与 date /t 命令相同的格式。由 Cmd.exe 生成。有关
date 命令的详细信息,请参阅 Date。
%ERRORLEVEL% 系统 返回上一条命令的错误代码。通常用非零值表示错误。
%HOMEDRIVE% 系统 返回连接到用户主目录的本地工作站驱动器号。基于主目录值而设置。用
户主目录是在“本地用户和组”中指定的。
%HOMEPATH% 系统 返回用户主目录的完整路径。基于主目录值而设置。用户主目录是在“本地用户和组”中指定的。
%HOMESHARE% 系统 返回用户的共享主目录的网络路径。基于主目录值而设置。用户主目录是
在“本地用户和组”中指定的。
%LOGONSERVER% 本地 返回验证当前登录会话的域控制器的名称。
%NUMBER_OF_PROCESSORS% 系统 指定安装在计算机上的处理器的数目。
%OS% 系统 返回操作系统名称。Windows 2000 显示其操作系统为 Windows_NT。
%PATH% 系统 指定可执行文件的搜索路径。
%PATHEXT% 系统 返回操作系统认为可执行的文件扩展名的列表。
%PROCESSOR_ARCHITECTURE% 系统 返回处理器的芯片体系结构。值:x86 或 IA64 基于
Itanium
%PROCESSOR_IDENTFIER% 系统 返回处理器说明。
%PROCESSOR_LEVEL% 系统 返回计算机上安装的处理器的型号。
%PROCESSOR_REVISION% 系统 返回处理器的版本号。
%PROMPT% 本地 返回当前解释程序的命令提示符设置。由 Cmd.exe 生成。
%RANDOM% 系统 返回 0 到 32767 之间的任意十进制数字。由 Cmd.exe 生成。
%SYSTEMDRIVE% 系统 返回包含 Windows server operating system 根目录(即系统根目录)
的驱动器。
%SYSTEMROOT% 系统 返回 Windows server operating system 根目录的位置。
%TEMP% 和 %TMP% 系统和用户 返回对当前登录用户可用的应用程序所使用的默认临时目录。
有些应用程序需要 TEMP,而其他应用程序则需要 TMP。
%TIME% 系统 返回当前时间。使用与 time /t 命令相同的格式。由 Cmd.exe 生成。有关
time 命令的详细信息,请参阅 Time。
%USERDOMAIN% 本地 返回包含用户帐户的域的名称。
%USERNAME% 本地 返回当前登录的用户的名称。
%USERPROFILE% 本地 返回当前用户的配置文件的位置。
%WINDIR% 系统 返回操作系统目录的位置。

其他系统变量

%1-%9代表调用命令时传递的参数,%*代表所有传递的参数

image.png

%0 这个不是返回参数的值了,他有两层意思!

第一层意思:返回批处理所在绝对路径
例子:
@echo off
echo %0
pause
保存为test.BAT放在桌面运行,会显示如下结果
“C:\Documents and Settings\Administrator\桌面\test.bat”
他把当前批处理执行的所在路经打印出来了,这就是返回批处理所在绝对路径的意思
第二层意思:无限循环执行BAT
例子:
@echo off
net user
%0
保存为BAT执行,他就会无限循环执行net user这条命令,直到你手动停止.
龙卷风补充:其实%0就是第一参数%1前面那个参数,当然就是批处理文件名(包括路径)。

27. 子程序

在批处理程序中可以调用外部可运行程序,比如exe程序,也可调用其他批处理程序,这些也可以看作子程序,但是不够方便,如果被调用的程序很多,就显得不够简明了,很繁琐。
在windowsXP中,批处理可以调用本程序中的一个程序段,相当于子程序,这些子程序一般放在主程序后面。

子程序调用格式:
CALL :label arguments

子程序语法:
:label
command1
command2
……
commandn
goto :eof

在子程序段中,参数%0指标签:label

子过程一般放在最后,并且注意在主程序最后要加上exit或跳转语句,避免错误的进入子过程。

子程序和主程序中的变量都是全局变量,其作用范围都是整个批处理程序。

传至子程序的参数在call语句中指定,在子程序中用%1、%2至%9的形式调用,而子程序返回主程序的数据只需在调用结束后直接引用就可以了,当然也可以指定返回变量,请看下面的例子。

子程序例1:
@echo off
call :sub return
echo 子程序返回值:%return%
pause
goto :eof

:sub
set %1=你好
goto :eof
运行结果:你好

子程序例2:设计一个求多个整数相加的子程序
@echo off
set sum=0
call :sub 10 20 35 40 50
echo 数据求和结果:%sum%
pause
goto :eof
:sub
rem 参数1为返回变量名称
set /a sum+=%1
shift /1
if not “%1”==”” goto sub
goto :eof

运行结果:155

28. 随机数

%RANDOM% 系统变量 返回 0 到 32767 之间的任意十进制数字。由 Cmd.exe 生成。

2的15次方等于32768,上面的0~32767实际就是15位二进制数的范围。
例:生成5个100以内的随机数
@echo off
setlocal enabledelayedexpansion
for /L %%i in (1 1 5) do (
set /a randomNum=!random!%%100
echo 随机数:!randomNum!
)
pause
运行结果:(每次运行不一样)
随机数:91
随机数:67
随机数:58
随机数:26
随机数:20
请按任意键继续. . .

通用的公式%random%%%(max-min+1)+min来产生[min,max]区间里的随机数,
注:批处理中求模得用两个%%符号。
比如,我们想获得4到12之间的随机数,就可以这样来使用,代码如下:
@REM 产生10个[4,12]间的随机数
@echo off
REM 启用延迟环境变量扩展
setlocal enabledelayedexpansion
REM 设置随机数的最小和最大值以及求模用的变量
set min=4
set max=12
set /a mod=!max!-!min!+1
for /l %%i in (1,1,10) do (
REM 产生[min,max]之间的随机数
set /a r=!random!%%!mod!+!min!
echo.
echo 随机数%%i:!r!)

思考题目:生成给定位数的随机密码
解答思路:将26个英文字母或10数字以及其它特殊字符组成一个字符串,随机抽取其中的若干字符。

  1. @echo off
  2. call :randomPassword 5 pass1 pass2
  3. echo %pass1% %pass2%
  4. pause
  5. exit
  6. :randomPassword
  7. ::---------生成随机密码
  8. ::---------%1为密码长度,%2及以后为返回变量名称
  9. ::---------for命令最多只能区分31个字段
  10. @echo off
  11. set password_len=%1
  12. if not defined password_len goto :eof
  13. if %password_len% lss 1 goto :eof
  14. set wordset=a b c d e f g h i j k l m n o p q r s t u v w x y z
  15. set return=
  16. set num=0
  17. :randomPassword1
  18. set /a num+=1
  19. set /a numof=%random%%%26+1
  20. for /f "tokens=%numof% delims= " %%i in ("%wordset%") do set return=%return%%%i
  21. if %num% lss %password_len% goto randomPassword1
  22. if not "%2"=="" set %2=%return%
  23. shift /2
  24. if not "%2"=="" goto randomPassword
  25. goto :eof
  1. @echo off
  2. call :randomPassword 6 pass1 pass2 pass3
  3. echo %pass1% ,%pass2% ,%pass3%
  4. pause
  5. goto :eof
  6. :randomPassword
  7. ::---------生成随机密码
  8. ::---------%1为密码长度,%2及以后为返回变量名称
  9. ::---------goto循环、变量嵌套、命令嵌套
  10. @echo off
  11. if "%1"=="" goto :eof
  12. if %1 lss 1 goto :eof
  13. set password_len=%1
  14. set return=
  15. set wordset=abcdefghijklmnopqrstuvwxyz023456789_
  16. ::---------------------------循环
  17. :randomPassword1
  18. ::---生成0-35之间的随即数
  19. set /a numof=%random%%%36
  20. ::---在wordset变量中,根据随机生成的随机数,截取一个字符,进行拼接
  21. call set return=%return%%%wordset:~%numof%,1%%
  22. set /a password_len-=1
  23. if %password_len% gtr 0 goto randomPassword1
  24. ::---------------------------循环
  25. if not "%2"=="" set %2=%return%
  26. shift /2
  27. if not "%2"=="" goto randomPassword
  28. goto :eof

29. 变量嵌套 与 命令嵌套

和其它编程语言相比,dos功能显得相对简单,要实现比较复杂的功能,需要充分运用各种技巧,变量嵌套与命令嵌套就是此类技巧之一。

先复习一下前面的“字符串截取”的关键内容:

**
截取功能统一语法格式为:%a:~[m[,n]]%
**
方括号表示可选,%为变量标识符,a为变量名,不可少,冒号用于分隔变量名和说明部分,符号~可以简单理解为“偏移”即可,m为偏移量(缺省为0),n为截取长度(缺省为全部)。

百分号如果需要当成单一字符,必须写成%%

以上是dos变量处理的通用格式,如果其中的m、n为变量,那么这种情况就是变量嵌套了。

比如设变量word为“abcdefghij”,变量num为“123456789”
%word:~4,1%为e,其中4可以从变量num中取值,即%num:~3,1%,写成组合形式如下:
%word:~%num:~3,1%,1% 经测试这种写法不能正确执行,写成%word:~(%num:~3,1%),1%同样不行,那么,怎么实现这种变量嵌套呢?这就必须结合命令嵌套。

什么是命令嵌套呢?简单的说,首先用一条dos命令生成一个字符串,而这个字符串是另一条dos命令,用call语句调用字符串将其执行,从而得到最终结果。

例:用call语句实现命令嵌套
@echo off
set str1=aaa echo ok bbb
echo 初始字符串:%str1%
echo 生成命令字符串如下:
echo %str1:~4,7%
echo 运行命令字符串生成最终结果为:
call %str1:~4,7%
pause

运行显示:
初始字符串:aaa echo ok bbb
生成命令字符串如下:
echo ok
运行命令字符串生成最终结果为:
ok
请按任意键继续. . .