学习 Bat 脚本
bat 语法
符号
| 符号 | 描述 |
| —- | ———————————————————— |
| @ | 隐藏命令回显 |
| ~ | for 中表示使用增强的变量扩展
在 set 中表示使用扩展变量指定位置字符串
在 set /a 中表示按位取反 |
| % | 两个%%包裹的字符串表示环境变量
%0 ~ %9 表示引用命令行参数
在 for 中表示循环变量
%% 表示在执行时变为一个 % |
| ^ | 取消转义字符
在 findstr /r 的 [] 表示不匹配的指定字符串 |
| & | 命令连接符(命令1 & 命令2)
在 set /a 中表示按位与 |
| * | 通配符
在 set /a 中为乘法
在 findstr /r 中表示前个字符多个匹配 |
| () | 括号中可多行命令
在 for 和 if 中常用 |
| - | 范围表示符
在 for 中的 tokens 可用到
跟在某些命令行 / 后表示取反向 |
| + | 用在 copy 中,将多个文件合成一个
在 set /a 中是加法 |
| \| | 管道符
将上一命令输出作为下一命令输入
在 set /a 中是按位或 |
| : | 标签定位符
可接受 goto 命令所指向的标签 (goto End) |
| " " | 界定符
在用带空格路径时将路径扩起
在 for /f 中表示将包含内容作为字符串分析
在 for /f “usebackq” |
| / | 其后的字符是命令的功能开关 |
| > | 定向符 将输出内容重定向到指定(文本) |
| » | 定向符 追加模式 |
| < | 输入定向符 从指定(文本)获取内容 |
| = | 赋值符号 |
| \ | 一般代表路径,findstr /r 中表示转义字符 |
| '' | 在for/f中表示将它们包含的内容当作命令行执行并分析其输出
在for/f “usebackq"中表示将它们包含的字符串当作字符串分析 |
| . | 一般表示路径 ./ 当前, ../ 上级, 文件名中的最后一个表示文件名和扩展名的分割 |
| && | 连接符 前面的执行完毕再执行后面的 |
| \|\| | 连接符 前面的没执行成功,就执行后面的 |
| $ | findstr 中表示一行的结束 |
| `` | for /f 中表示将内容作为命令并分析输出 |
| [] | 在帮助文档中表示内容可选,findstr /r 中表示指定字符集匹配 |
| ? | 通配符 单个字符 |
| ! | 变量延迟启用是,以!!将变量名括起标识对变量值的引用 |
命令
echo 输出内容
echo [on | off] [message]
- on | off 指定是否允许命令回显
- message 为输出内容
:关闭回显
@echo off
:打印123
echo 123
pause 暂停
需要按任意键继续。
pause
注释
单行注释
rem [message]
- message 指定屏蔽的命令或注释
::注释内容
:注释内容 不能包含 goto 可指向的标签
goto 标签 注释内容(用作 goto 说明)
:标签 注释内容
多行注释
goto start
可以是多行文本或命令
可以包含重定向符号或其他字符串
只要不包含 :start 就都是注释
wwaaw
awawa
:start
重定向符 > »
用于将命令输出写到指定位置。
如 写入文件、nul(空设备)。
>
将输出写入指定文件,nul(空设备,用于放弃输出)等。
会覆盖文件已有内容。
»
与 > 符号类似,不过是追加而非覆盖。
屏蔽错误
:ipcnogif 是一个错误命令 将会报错
ipcnogif > nul 2 > nul
:会隐藏此命令报错
:> nul 等效于 1 > nul
:> nul 前的 1 表示输出流 2 表示错误流(1可省略)
文件参数
批处理中可引用参数为 %0 ~ %9。
%0 表示批处理文件本身。
%1 ~ %9 则是批处理参数。
也称形参。
超过 9 个参数时
使用 shift 命令进行偏移。
如果参数未传入,则变量为空。
@echo off
echo %1 %9
shif /0
:偏移0
echo %1 %2 ...
shif /1
:偏移1
errorlevel 错误等级
常用于判断上个命令的执行情况。
一般上条命令执行结果只有 1(失败)或 0(成功)。
实际上 errorlevel 值范围在 0~255 之间。
比如 xcopy 的 errorlevel 就有五个值。
- 0 复制文件成功。
- 1 未找到复制文件。
- 2 用户通过 ctrl + c 终止操作。
- 4 初始化错误。
- 5 磁盘写入错误。
比较
| 参数 | 描述 | 例子 |
| —- | ———– | ———- |
| EQU | 等于 = | if 1 EQU 1 |
| NEQ | 不等于 != | if 1 NEQ 1 |
| LSS | 小于 < | if 1 LSS 1 |
| LEQ | 小于等于 <= | if 1 LEQ 1 |
| GTR | 大于 > | if 1 GTR 1 |
| GEQ | 大于等于 >= | if 1 GEQ 1 |
set
set [variable=[string]]
- variable 指定变量名 不允许包含 等号(=)
- string 指定派给变量的值
如果需要显示当前环境变量,可直接 set Variable
会直接输出变量值。
启用变量扩展后,set p
会查找所有以 p 开头的变量。
如果未找到,则 errorlevel 变更为 1。
扩展命令
set /a 数字表达式
set /p 提示字符串
- /a
| 操作符 | 描述 |
| ———————————- | ———— |
| () | 分组 |
| ! ~ - | 一元运算符 |
| * / % | 算数运算符 |
| « » | 逻辑移位 |
| | 按位“与” |
| | 按位“异” |
| \| | 按位“或” |
| = *= /= %= += -= &= = \|= «= »= | 赋值 |
| , | 表达式分隔符 |
- /p
将变量设置为用户输入,会提示预设提示字符串。
环境变量替换
%path:str1=str2%
- path 变量名称
- str1 替换的原字符串
- str2 替换后的字符串
子字符串
%path:~10,5%
以上会截取该变量偏移量从十个开始的五个字符。
如果两个数字(偏移量和长度)都是负数,使用的数字则是环境变量数值长度加上指定的偏移量或长度。
延迟环境变量
使用 cmd /V:on
启用。
set var=1
if %var% == 1 (
set var=2
:将永远不会执行
:因为读到第一个 if 时,两个 %var% 会被代替
if %var% == 2 echo 2
)
启用后将允许使用 !
符号在执行时扩展变量。
set var=1
if %var% == 1 (
set var=2
:将会执行
if !var! == 2 echo 2
)
如果命令扩展被启用,有几个动态环境变量可以被扩展,但不会出现在 SET 显示的变量列表中。每次变量数值被扩展时,这些变量数值都会被动态计算。如果用户用这些名称中任何一个明确定义变量,那个定义会替代下面描述的动态定义:
- %CD% - 扩展到当前目录字符串。
- %DATE% - 用跟 DATE 命令同样的格式扩展到当前日期。
- %TIME% - 用跟 TIME 命令同样的格式扩展到当前时间。
- %RANDOM% - 扩展到 0 和 32767 之间的任意十进制数字。
- %ERRORLEVEL% - 扩展到当前 ERRORLEVEL 数值。
- %CMDEXTVERSION% - 扩展到当前命令处理器扩展版本号。
- %CMDCMDLINE% - 扩展到调用命令处理器的原始命令行。
- %HIGHESTNUMANODENUMBER% - 扩展到此计算机上的最高 NUMA 节点号。
setlocal 和 endlocal
创建一个作用域。
所有的环境改动只限于此批处理文件。
无论在 setlocal 命令之前它们的设置是什么,这些修改会一直保留到匹配的 endlocal 命令。
接受参数:
- enableextensions / disableextensions 启用或禁用命令处理器扩展。这些参数比 cmd /e:on 或 /e:off 开关有优先权。请参阅 cmd /? 获取详细信息。
- enabledelayedexpansion / disabledelayedexpansion 启用或禁用延缓环境变量扩展。这些参数比 cmd /v:on 或 /v:off 开关有优先权。请参阅 cmd /? 获取详细信息。
@ECHO OFF
VERIFY OTHER 2>nul
SETLOCAL ENABLEEXTENSIONS
:在 cmd.exe 的旧版本上,setlocal 未设置 errorlevel 值。具有不正确参数的 verify 命令将 errorlevel值初始化成非零值。
IF ERRORLEVEL 1 ``echo` `Unable to ``enable` `extensions
设备
| 名称 | 描述 |
| —— | ———————- |
| con | 控制台(键盘、显示器) |
| aux | com1 - com4 所有串口 |
| prn | lpt1 - lpt3 所有并口 |
| nul | 空设备 |
| clock$ | 电子钟 |
路径
%cd%
%cd% 返回的是当前执行环境目录(如果是DOS窗口,则是DOS窗口里面的路径),并非是 bat 脚本实际所在的路径。
%~dp0
%~dp0 可以用来获取批处理文件的实际路径,与当前 DOS 环境所在的目录没有关系。其中:
- %~dp0 的 “d” 为 Drive 的缩写,即为驱动器,磁盘。
- %~dp0 的 “p” 为 Path 缩写,即为路径,目录。
更多选项语法:
- ~0 删除任何引号(“),扩充 %0
- %~d0 仅将 %0 扩充到一个驱动器号
- %~f0 将 %0 扩充到一个完全合格的路径名(“f” 是 file,即文件)
- %~p0 仅将 %0 扩充到一个路径
- %~n0 仅将 %0 扩充到一个文件名(“n” 是 name 文件名)
- %~x0 仅将 %0 扩充到一个文件扩展名
- %~s0 扩充的路径只含有短名(“s” 为 Short,短的)
- %~a0 将 %0 扩充到文件的文件属性(“a” 为 attribute,即属性)
- %~t0 将 %0 扩充到文件的日期/时间(“t” time)
- %~z0 将 %0 扩充到文件的大小(Size 大小)
- %~$PATH:0 查找列在路径环境变量的目录,并将 %0 扩充到找到的第一个完全合格的名称。如果环境变量名未被定义,或者没有找到文件,此组合键会扩充到空字符串
可以组合修饰符来得到多重结果:
- %~dp0 仅将 %0 扩充到一个驱动器号和路径
- %~nx0 仅将 %0 扩充到一个文件名和扩展名
- %~fs0 仅将 %0 扩充到一个带有短名的完整路径名
- %~dp$PATH:0 查找列在路径环境变量的目录,并将 %I 扩充到找到的第一个驱动器号和路径。
- %~ftza0 将 %0 扩充到类似输出线路的 DIR
- %0 为当前批处理文件。如果0换成1为第一个文件,2为第2个
if-else
IF [NOT] ERRORLEVEL number command
IF [NOT] string1==string2 command
IF [NOT] EXIST filename commnd
if () else ()
if () else if () else()
if () ^
else if () ^
else ()
- NOT 将表达式的结果取反。
- ERRORLEVEL number 如果最后运行的程序返回一个等于或大于指定数字的退出代码。
- string1==string2 如果指定的字符串 string1 等于 string2。
- EXIST filename 如果指定的文件名存在。
- command 如果符合条件(即表达式为TRUE),指定要执行的命令。如果指定的条件为 FALSE,命令后可跟 ELSE 命令,该命令将在 ELSE 关键字之后执行该命令。
扩展
IF [/I] string1 compare-op string2 command
IF CMDEXTVERSION number command
IF DEFINED variable command
其中, compare-op 可以是:
- EQU - 等于
- NEQ - 不等于
- LSS - 小于
- LEQ - 小于或等于
- GTR - 大于
- GEQ - 大于或等于
/I 则表示不区分大小写。
CMDEXTVERSION 条件的作用跟 ERRORLEVEL 的一样,除了它是在跟与命令扩展有关联的内部版本号比较。第一个版本是 1。每次对命令扩展有相当大的增强时,版本号会增加一个。命令扩展被停用时,CMDEXTVERSION 条件不是真的。
如果已定义环境变量,DEFINED 条件的作用跟 EXIST 的一样,除了它取得一个环境变量,返回的结果是 true。
goto
REM 跳转到 myLabel 标签
goto myLabel
REM 语句1(在 myLabel 之前的语句将不会执行)
REM 定义了一个标签
:myLabel
REM 语句2(执行该语句,因为 goto 跳转到了 myLabel 标签)
for
REM 在 CMD 窗口中
FOR %variable IN (set) DO command [command-parameters]
REM 在批处理文件中
FOR %%variable IN (set) DO command [command-parameters]
- %variable 指定一个单一字母可替换的参数,该参数用来存放 for 语句每次迭代的数据。
- (set) 指定一个或一组文件,可以使用通配符。
- command 指定对每个文件执行的命令。
- command-parameters 为特定命令指定参数或命令行开关。
/d 扩展
使用后,将于目录名匹配而不是默认的文件名。
/r 扩展
FOR /R [[drive:]path] %variable IN (set) DO command [command-parameters]
将递归进入根目录树 [Drive:]Path,在树的每个目录中执行 for 语句。如果在 /R 后没有指定目录,则认为是当前目录。如果 set 只是一个句点(.),则只枚举目录树。
/l 扩展
FOR /L %variable IN (start,step,end) DO command [command-parameters]
for /L 表示以增量形式从 start 以每次增加 step,直到到 end 的一个数字序列。如果 start 小于 end,就会执行该命令。如果迭代变量超过 end,则命令解释程序退出此循环。还可以使用负的 step 以递减数值的方式逐步执行此范围内的值。其他参数说明:
- start:指定创建序列的开始位置
- step:for 语句创建序列时单步距离。
- end:指定创建序列结束位置
/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]
/F 扩展是 for 语句最常用的、也是最强的命令。主要用来处理文件和一些命令的输出结果。它可以提取文本文件的内容,进行逐行分析和处理。
file-set 为一个或多个文件名。for 语句会逐一分析指定的每个文件,打开指定文件、读取并处理文件内容。处理包括读取文件内容,将文件内容逐行读取,然后将每行解析成零或更多的符号(默认使用空格作为分隔符)。
高级选项
eol=[string]
会忽略以指定 string 开头的行。不进行处理。
skip=[number]
会跳过开头 number 行。
delims=[string]
指定 string 符号为分割符号集合(多个字符时,空格放在最后),并替换默认的空格和制表符。
tokens=x,y,m-n
tokens=m 表示提取第m列;
tokens=m,n 表示提取第m列和第n列;
tokens=m-n 表示提取第m列至第n列;
tokens=* 忽略行首的所有空格;
tokens=m* 提取第m列以后的所有字符,星号表示剩余的字符;
/f 扩展 usebackq 选项
usebackq 命令的功能和意义不是很明朗,据说是由机器自动添加进去的,因此它变得可有可无,我们写代码时可无,机器执行时可有。但可以肯定的是,启用该选项时,它会改变“FOR /F“解析文本的功能,集合内原有引号功能失效,因此需要变成新的引号。
FOR /F "eol=; tokens=2,3* delims=, " %i in (myfile.txt) do @echo %i %j %k
goto end
会分析 myfile.txt 中的每一行,忽略以分号打头的那些行,将每行中的第二个和第三个符号传递给 for 函数体,用逗号和/或空格分隔符号。请注意,此 for 函数体的语句引用 %i 来获得第二个符号,引用 %j 来获得第三个符号,引用 %k 来获得第三个符号后的所有剩余符号。对于带有空格的文件名,你需要用双引号将文件名括起来。为了用这种方式来使用双引号,还需要使用 usebackq 选项,否则,双引号会被理解成是用作定义某个要分析的字符串。
%i 在 for 语句中显式声明,%j 和 %k 是通过tokens= 选项隐式声明的。可以通过 tokens= 一行指定最多 26 个符号,只要不试图声明一个高于字母 "z" 或"Z" 的变量。请记住,FOR 变量是单一字母、分大小写和全局的变量;而且,不能同时使用超过 52 个(a-zA-Z 等于 26+26)。
:end