批处理(Batch),即批处理脚本,批处理就是对某对象进行批量的处理,是一种简化的脚本语言,在Windows系统中,扩展名为.bat的文件是一个可执行文件,它由一系列的命令构成,其中可以包含对其他程序的调用,这个文件的每一行都是一条DOS命令。批处理通常用于自动执行重复性任务,只需双击批处理文件便可执行任务,而无需重复输入相同指令,通过编写批处理文件,实现自动批量的执行DOS命令来进行特定的操作,可以提高我们的工作效率。
01
Bat批处理常用的命令和符号
echo
echo是用来显示此命令后的字符。
语法格式:
echo [on|off] [message]
参数说明:
on | off 指定是否允许命令的回显。若要显示当前的 echo 的设置,可使用不带参数的 echo 命令。
message 指定让 MS-DOS 在屏幕上显示的正文。
实例:在DOS控制台中输出 “hello world”
@echo off
echo hello world
pause
脚本说明:
(1)@ 表示不在 DOS 窗口中显示 echo off 命令;
(2)echo off 表示后续命令在 DOS 窗口中不显示;
(3)echo hello world 表示将在 DOS窗口 中显示 “hello world”字符串;
(4)pause 表示脚本执行完成后,不立即关闭 DOS 窗口,而是提示 “请按任意键继续...” 信息。当用户按了任意键,DOS 窗口才关闭;
运行结果:
@(命令行回显屏蔽符 )
@ 符号的作用是使批处理程序中执行的命令行不在 DOS 窗口中显示。
通过下面两个bat脚本运行结果对比就知道@是什么作用了;
不带@的脚本:
echo hello world
pause
运行结果:
加上@的脚本:
@echo hello world
@pause
运行结果:
@ 和 echo off 的区别:
@ 符号与 echo off 功能相似,都是用来屏蔽命令在 DOS窗口中输出,但 @ 符号是加在每个命令行的最前面,表示运行时不显示这一行的命令行, echo off 则是隐藏该命令后面的所有命令,不包括echo off本身,所以echo off前面要加一个@,这样echo off也可以不显示在DOS窗口中了。
pause
运行 pause 语句会暂停批处理的执行并在屏幕上显示 “请按任意键继续 . . .” 的提示
02
批处理注释
一个好的脚本注释是必要的,注释是用来对脚本功能的说明,添加注释能提高脚本的可读性,注释是不会被执行的。
rem
rem 在批处理文件中加入注解,也可用 rem 命令来屏蔽命令。
语法格式:
REM [string]
参数说明:
string 指定要屏蔽的命令或要包含的注解。
实例:使用 rem 命令添加注释和屏蔽命令 “echo hello world”。
@echo off
rem 这是一行注释
rem echo hello world
pause
运行结果:
其他形式的注释:
@echo off
rem 一种比较常用的注释方法
goto start
= 可以是多行文本,可以是命令
= 可以包含重定向符号和其他特殊字符
= 只要不包含 :start 这一行,就都是注释
:start
:: 注释内容(第一个冒号后也可以跟任何一个非字母数字的字符)
echo 注释内容(不能出现重定向符号和管道符号)> nul
if not exist nul 注释内容(不能出现重定向符号和管道符号)
:注释内容(注释文本不能与已有标签重名)
rem 可以用作行间注释(不能出现重定向符号和管道符号)
%注释内容%
goto 标签 注释内容(可以用作说明goto的条件和执行内容)
:标签 注释内容(可以用作标签下方段的执行内容)
pause
运行结果:
03
重定向符号 > 和 >>
在 bat 中,重定向符号 > 和 >> 用于将某条命令的输出写到指定的地方,如写入到文件、nul(空设备)。
重定向符号 >
在批处理中 > 符号实现重定向,可将命令的输出写入到指定的文件或者nul(nul 是空设备名,像个黑洞,往往用来屏蔽错误输出等) 等位置。
注意:> 符会覆盖文件中已有的内容。
实例:将 ping 命令的输出信息输出到 ping.txt 文件。
@echo off
ping www.baidu.com > ping.txt
ping www.hao123.com > ping.txt
echo finished
pause
运行结果:
在脚本的当前目录下生成了一个ping.txt文件,ping.txt的内容只有一条ping的结果,因为第一条ping命令被第二条ping命令的输出内容给覆盖了。
重定向符号 >>
>> 符号和 > 符号作用类似,也可将命令的输出写入到指定的文件或nul等位置,不同的是,>> 符号会将当前命令的结果直接追加到指定文件的最后面。
实例:将 ping 命令的结果写入到 ping.txt 文件。
@echo off
ping www.baidu.com >> ping.txt
ping www.hao123.com >> ping.txt
echo finished
pause
运行结果:
保存了两条ping命令的结果。
屏蔽批处理错误
假如我们在写脚本的时候,写错了,比如下面的脚本copy写成了coyp;
@echo off
coyp a.txt bak/b.txt
if %errorlevel%==0 (
echo SUCCESS
) else (
echo ERROR
)
pause
运行结果:
结果中输出了 “'coyp' 不是内部或外部命令,也不是可运行的程序或批处理文件” 错误信息,这里可以使用重定向符号隐藏这个错误信息,脚本如下:
@echo off
coyp a.txt bak/b.txt >nul 2>nul
if %errorlevel%==0 (
echo SUCCESS
) else (
echo ERROR
)
pause
运行结果:
>nul 2>nul 是把命令执行的输出信息和错误信息不输出到屏幕,而是输出到一个根本不存在的设备,>nul 等效于 1>nul,>nul 前面的 1 表示输出流,2 表示错误流(1可以省略不写)
04
批处理文件参数
批处理脚本中可引用的参数为 %0~%9,%0 是指批处理文件的本身,也可以说是一个外部命令;%1~%9是批处理参数,也称形参。
实例演示:
@echo off
echo 参数0=%0
echo 参数1=%1
echo 参数2=%2
echo 参数3=%3
echo 参数4=%4
echo 参数5=%5
echo 参数6=%6
echo 参数7=%7
echo 参数8=%8
echo 参数9=%9
pause
将上面脚本保存到 1.bat 文件,然后打开cmd窗口,切换到Desktop(桌面)目录下,输入 “1.bat A B C D E F G H I”敲回车,运行结果:
接收多于 %1~%9 个参数
假如替换形参的实参超过了批处理脚本中所规定数值(9个,1%到%9共9个)且想在批处理文件中应用这些实参的话,可以用shift 命令来实现。
实例演示用 shift 命令接收更多参数:
@echo off
echo %1 %2 %3 %4 %5 %6 %7 %8 %9
shift /0
echo %1 %2 %3 %4 %5 %6 %7 %8 %9
shift /1
echo %1 %2 %3 %4 %5 %6 %7 %8 %9
shift /2
echo %1 %2 %3 %4 %5 %6 %7 %8 %9
shift /3
echo %1 %2 %3 %4 %5 %6 %7 %8 %9
shift /4
echo %1 %2 %3 %4 %5 %6 %7 %8 %9
shift /5
echo %1 %2 %3 %4 %5 %6 %7 %8 %9
shift /6
echo %1 %2 %3 %4 %5 %6 %7 %8 %9
shift /7
echo %1 %2 %3 %4 %5 %6 %7 %8 %9
shift /8
echo %1 %2 %3 %4 %5 %6 %7 %8 %9
pause
将上面脚本保存到 1.bat 文件,然后打开cmd窗口,切换到Desktop(桌面)目录下,输入 “1.bat A B C D E F G H A M N D W F G J K K J I”敲回车,运行结果:
ITPro进化论
///
上一篇文章分享了Bat批处理的部分基础知识,包括echo、@、pause命令、批处理注释、重定向符号、批处理文件参数,今天继续分享Bat批处理的基础知识set命令和延迟环境变量扩展。
1
set命令
set 命令用来显示、设置或删除 cmd.exe 环境变量,set 命令在编写批处理脚本时使用频率非常高,语法如下:
SET [variable=[string]]
参数说明:
variable 指定环境变量名。
string 指定要指派给变量的一系列字符串。
显示当前环境变量,键入不带参数的 SET。实例:
上图显示了path和tmp环境变量的值,即下图电脑上设置的环境变量;
set后面还可以只跟一个字母,即可列出以这个字母开头的变量名和值;
如果在当前环境中找不到该变量名称,SET 命令将把 ERRORLEVEL设置成 1,如下实例:
@echo off
set tmp
echo errorlevel=%errorlevel%
set java
echo errorlevel=%errorlevel%
pause
运行结果:
在使用set进行赋值时,有几个注意事项:
①等号两边不要有空格。
②变量值包含特殊字符需用双引号。
③避免使用系统环境变量同名的自定义变量。
SET扩展命令 /A 和 /P
/A 命令
/A 命令行开关指定等号右边的字符串为被评估的数字表达式。该表达式解析很简单并以递减的优先权顺序支持下列操作:
操作符 | 描述 |
() | 分组 |
! ~ | 一元运算符 |
* / % | 算数运算符 |
+ - | 算数运算符 |
<< >> | 逻辑移位 |
& | 按位“与” |
^ | 按位“异” |
| | 按位“或” |
= *= /= %= += -= &= ^= |= <<= >>= | 赋值 |
, | 表达式分隔符 |
/A参数就是让SET可以支持数学符号进行加减等一些数学运算。
在使用任何逻辑或取余操作符时, 需要将表达式字符串用引号扩起来,在表达式中的任何非数字字符串键作为环境变量名称,这些环境变量名称的值已在使用前转换成数字。
实例:
@echo off
::使用 /A 执行加法运算,val=15。
set /A val=6+9
echo %val%
::将 val 环境变量加6,赋值给val2环境变量,val=25。
set /A val2=%val%+10
echo %val2%
::将 11 使用位移操作符,向右移动一位,移动一位等于除以2,val=5。
set /A "val3=13>>1"
echo %val3%
::使用分组符号提升加法的优先级,val=30。
set /A val4=(0+1+2+3+4+5+6+7+8+9)/3*2
echo %val4%
::使用 %% 进行取余运算,val=2。
set /A "val5=82%%10"
echo %val5%
pause
运行结果:
如果指定了一个环境变量名称,但未在当前环境中定义,那么值将被定为零,可以使用环境变量值做计算而不用键入那些 % 符号来得到它们的值。如下实例:
@echo off
::下面在 set 中使用A 参与运算,但是 tmp 并没有定义
::默认 A 为 0,因此 val=22
set /A val=A+22
echo %val%
::下面在 set 中使用 %B% 获取变量 B 的值,B=11,
::因此val2=33
set B=11
set /A val2=%B%+22
echo %val2%
pause
运行结果:
/P 命令
/P 命令行开关允许将变量数值设成用户输入的一行输入。读取输入行之前,显示指定的 promptString。promptString 可以是空的。语法:
set /P variateName=promptStrig
说明:
variateName 为变量名
promptStrig 为提示字符串,将在 DOS 窗口中显示
实例:
@echo off
::提示用户输入姓名,username为变量名,“请输入姓名”为提示信息。
set /p username=请输入姓名:
echo 你的姓名:%username%
pause
运行结果:
变量替换
%变量名称:变量1=变量2%
用“变量2”替代结果中的每一个“变量1”。
实例:
@echo off
set val=hello world! it's good world!
echo %val%
::将val值中的所有world替换成man
echo %val:world=man%
pause
运行结果:
%变量名称:变量1=变量2%,当“变量2”为空时,可以删除所有“变量1”。
实例:
@echo off
set val=hello world! it's good world!
echo %val%
::将val值中的所有l替换成空值
echo %val:l=%
pause
运行结果:
%变量名称:变量1=变量2%,当“变量2”前面加符号 * 时,可以替换“变量1”中第一次出现“变量2”之前的所有字符。
实例:
@echo off
set val=hello world! it's good world!
echo %val%
::将val值中的第一个l之前的所有字符替换成AA
echo %val:*l=AA%
pause
运行结果:
子字符串
%变量名:~10,6%
只使用变量中从第 11 个(偏移量 10)字符开始的6个字符;如果没有指定长度,则显示剩余所有字符;
如果偏移量和长度都是负数,使用的数字则是环境变量数值长度加上指定的偏移量或长度。
实例:
@echo off
set val=hello world! it's good world!
echo %val%
::截取val值中第6个字符开始的后面3个字符
echo %val:~6,3%
::如果没有指定长度,则采用默认值,即显示变量值剩下的所有字符。
echo %val:~6%
::提取 val 变量的最后6个字符
echo %val:~-6%
::从倒数第6个字符开始,提取3个字符
echo %val:~-6,3%
::提取 val 变量的所有字符,除了最后两个
echo %val:~0,-3%
::提取倒数第6个字符开始到结尾的字符,除了最后3个字符
echo %val:~-6,-3%
pause
运行结果:
2
延迟环境变量扩展
在CMD命令窗口中:
/V:ON 启用延迟环境变量扩展,变量名使用 ! 作为分隔符。
/V:OFF 禁用延迟的环境扩展。
如下图,在没有开启延迟环境变量扩展时,echo !val!是原样输出变量名,并没有输出变量值,通过/V:NO开启延迟环境变量扩展后,echo !val!输出了变量值。
为了理解什么是延迟环境变量扩展,我们先来看一下什么是变量扩展;
在CMD在解释命令的时候,会先读取命令行一条完整的命令,然后对其进行一些命令格式的匹配操作,核对一下所输入的命令格式是不是符合他的要求,在变量名字两边加一个%号,如%name%,当CMD在对读取整行命令进行格式匹配时,发现name这个字符两边加了%号,就不会把它当作普通字符处理,而是会把它当作一个变量处理,变量名叫name;然后CMD就会找到变量名对应的值,用变量名的值替换掉这个变量名字(name),如果变量名不存在值,就返回空值,再将这个替换好并且匹配的命令执行,这个替换值的过程,就叫变量扩展;说白了就是把变量的名字,用它的值给替换掉后执行,也就是批处理如何识别一个变量的过程。
变量扩展的例子:
@echo off
set AA=123
set var=%AA%
echo %var%
pause
运行结果:
CMD在读取到echo %var%这条命令后,就会进行匹配操作,它发现var字符两边有%号,这时就会%var%当作一个变量处理,查看这个var变量名是不是有值,如果有就用var的值把变量名var给替换掉,echo %var%的上一条命令set var=%AA%中,给var赋值为%AA%,所以会用AA变量把%var%这个变量名替换掉,替换后的结果为echo %AA%,匹配完后,再执行echo %AA%这条语句,这时它会发现AA也是一个变量,就会继续向上找,把123替换过来,这时CMD中就会echo出一个123了。
那为什么要用延迟环境变量扩展呢?
CMD在解释命令时,会先把一条完整的命令进行读取,然后进行匹配操作,匹配时它会把命令里的变量用变量的值替换掉,然后执行这个替换好的命令。在Bat批处理脚本中,IF FOR这样的命令都可以加括号,将一些命令嵌套在里面执行,这样的话对于一条可以加扩号嵌套其它命令的命令,它的完整格式就是for %%i in (....)这样一个整体,如果我们在括号里面嵌入一些设置变量值的命令,就会出现问题了。
看下面的例子:
@echo off
for /l %%i in (1,2,6) do (
set var=%%i
echo %var%
)
pause
运行结果:
上面的代码整个作为一个完整的命令来处理,当作一个整体,读取到内存中,然后进行预处理,此时的 set var=%%i 并不是做赋值处理 而是当作字符放入批处理,所以echo的时候 var 其实还是空值,打印的时候会报错。
在命令中加入一条:setloacl ENABLEDELAYEDEXPANSION 启用延迟环境变量扩展,打印的时候就不会报错了。
注意:启用延迟环境变量扩展后,变量名要用!分隔。
@echo off
::启用延迟环境变量扩展
setlocal ENABLEDELAYEDEXPANSION
for /l %%i in (1,2,6) do (
set var=%%i
echo !var!
)
pause
运行结果:
延迟变量全称"延迟环境变量扩展", 是为了解决在for语句这类嵌套命令的命令中无法设置变量值的问题以及通过连接符执行的命令的问题。
通过连接符执行的命令的例子:
@echo off
::此时整句作为预处理加载到内存,var并没有被赋值,还是个空值
set var=AA & echo %var%
pause
运行结果:
开启延迟环境变量扩展(%var%要换成!var!):
@echo off
::开启延迟环境变量扩展
setlocal ENABLEDELAYEDEXPANSION
set var=AA & echo !var!
pause
运行结果:
ITPro进化论
给小编加个鸡腿🍗
///
上一篇文章分享了Bat批处理的部分基础知识,包括echo、@、pause命令、批处理注释、重定向符号、批处理文件参数,今天继续分享Bat批处理的基础知识errorlevel、setlocal/endlocal 命令、shift 命令、获取磁盘路径 %~dp0。
1
errorlevel 基础用法
errorlevel 用来判断上条命令的返回值,在 if /? 语句的帮助文档中有说明,如下图:
if errorlevel number command,意思是:如果返回的错误码值大于或等于number值的时候,则执行cmmand 操作。
实例:
@echo off
coyp 1.txt bak/2.txt
echo errorlevel=%errorlevel%
if errorlevel 0 echo SUCCESS
pause
运行结果:
可以看到errolevel=9009,errolevel的值大于0,所以输出了SUCCESS;将if errorlevel 0 echo SUCCESS中的0改为9010,结果如下图:
没有输出SUCCESS,因为errolevel的值小于9010,所以没有执行echo SUCCESS。
还有另外一种句式,if %errorlevel%==值 cmmand ,意思是:如果返回的错误码值等于值的时候,将执行cmmand操作。
实例:
@echo off
coyp 1.txt bak/2.txt
echo errorlevel=%errorlevel%
if %errorlevel%==0 (
echo success
) else (
echo error
)
pause
运行结果:
if %errorlevel%==0是判断errorlevel是否等于0,因为errolevel的值等于9009,所以执行了echo error,当把命令改成if %errorlevel%==9009时,输出了success。
一般情况下,一条命令的执行结果返回的值只有两个:“成功”用 0 表示;“失败”用 1 表示;实际上,errorlevel 返回值可以在0~255 之间,例如 xcopy 默认的errorlevel 值有5 个,分别表示5 种执行状态:
0 表示复制文件成功
1 没有找到复制文件
2 通过CTRL + C 终止了xcopy操作
4 初始化错误
5 磁盘写入错误
if %ERRORLEVEL% 对数值的比较方法不仅仅限于等于,还可以使用参数来控制。
比较参数如下:
EQU ——等于
NEQ ——不等于
LSS —— 小于
LEQ —— 小于或等于
GTR —— 大于
GEQ —— 大于或等于
2
setlocal/endlocal 命令
setlocal 和 endlocal 命令是用来定义一个局部区域,这个局部区域中的环境变量任何变化都不会改变原先的环境变量。
在执行 setlocal 之后所做的环境改动只限于批处理文件,要还原原先的设置,必须执行 endlocal ,达到批处理文件结尾时,对于该批处理文件的每个尚未执行的 setlocal 命令,都会有一个隐含的 endlocal 被执行。
无论在 setlocal 命令之前它们的设置是什么,这些修改会一直保留到匹配的 endlocal 命令。
endlocal结束批处理文件中环境改动的本地化操作,在执行 endlocal 之后所做的环境改动不再仅限于批处理文件,批处理文件结束后,原先的设置无法还原。
实例:
@echo off
set test=“ABC” &::设置test的变量值为“ABC”
echo setlocal定义区域之前:
set test
pause
setlocal &::开始定义局部区域
set test=“DEF” &::设置test的变量值为“DEF”
echo setlocal定义局部区域并设置test的值为“DEF”
set test
pause
endlocal &::结束局部区域
echo endlocal之后结束局部区域,test值恢复最初值
set test
pause
运行结果:
在setlocal定义的局部区域,设置了test=“DEF”,当通过endlocal结束定义的局部区域后,test的值恢复成最开始设置的“ABC”。
3
shift 命令
shift 命令用于更改批处理文件处理参数的方式,如指定起始处理参数的位置等。
实例:利用 shift 命令动态输出批处理执行时输入的所有参数。
@echo off
:round
if "%1"=="" goto cmd1
echo 参数:%1
shift
goto round
:cmd1
echo 没有获取到参数,结束脚本
goto end
:end
运行结果:
实例:使用 shift /n 的方式重新设置处理参数的起止位置。
@echo off
echo 参数1:%1
echo 参数2:%2
运行结果:
运行上面实例,传递了5个参数,分别是:A1 B2 C3 D5 E6
在执行 echo 之前添加 “shift /2” 命令,cmd.exe 将把传递参数的起始位置设置为2,即 %3 移动到 %2。代码如下:
@echo off
shift /2
echo 参数1:%1
echo 参数2:%2
运行结果:
4
获取磁盘路径 %~dp0
%cd% 或者 %~dp0 用来获取当前目录路径。
%cd%
%cd% 扩展到当前目录字符串。需要注意的是,这里的当前目录有可能和脚本实际所在目录不一致。实例:
@echo off
set BPath=%cd%
echo %BPath%
pause
运行结果:
%cd% 返回的是当前执行环境目录。
%~dp0
%~dp0 可以用来获取批处理文件的实际路径,与当前 DOS 环境所在的目录没有关系。其中:
%~dp0 的 “d” 为 Drive 的缩写,即为驱动器,磁盘;
%~dp0 的 “p” 为 Path 缩写,即为路径,目录;
可以使用 cd 命令转到 %~dp0 返回的目录,不过推荐使用 cd /d %~dp0。
实例:获取批处理文件自身磁盘路径。
@echo off 把1.bat文件放到D盘,运行结果:
set BPath=%~dp0
echo %BPath%
pause
更多选项语法:
~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 扩充到找到的第一个完全合格的名称。如果环境变量名未被定义,或者没有找到文件,此组合键会扩充到空字符串。
实例:查看每个选项的输出结果。
@echo off
REM C:
echo %~d0
REM C:\Users\Administrator\Desktop\1.bat
echo %~f0
REM \Users\Administrator\Desktop\
echo %~p0
REM 1
echo %~n0
REM .bat
echo %~x0
REM C:\Users\Administrator\Desktop\1.bat
echo %~s0
REM --a------
echo %~a0
REM 2023/04/16 20:17
echo %~t0
REM 337
echo %~z0
pause
运行结果:
可以组合修饰符来得到多重结果:
%~dp0 仅将 %0 扩充到一个驱动器号和路径
%~nx0 仅将 %0 扩充到一个文件名和扩展名
%~fs0 仅将 %0 扩充到一个带有短名的完整路径名
%~dp$PATH:0 查找列在路径环境变量的目录,并将 %I 扩充到找到的第一个驱动器号和路径。
%~ftza0 将 %0 扩充到类似输出线路的 DIR
%0 为当前批处理文件。如果0换成1为第一个文件,2为第2个。
@echo off
REM C:\Users\Administrator\Desktop\
echo %~dp0
REM 1.bat
echo %~nx0
REM C:\Users\Administrator\Desktop\1.bat
echo %~fs0
REM C:\Users\Administrator\Desktop\
echo %~dp$PATH:0
REM --a-------- 2023/04/16 20:30 258 C:\Users\Administrator\Desktop\1.bat
echo %~ftza0
REM C:\Users\Administrator\Desktop\1.bat
echo %~0
pause
运行结果:
%cd% 和 %~dp0 均可以获取到当前路径, %~dp0 获取的是批处理文件所在目录的路径,%cd% 获取的是当前 DOS 环境的路径。如果批处理文件和执行批处理文件不再同一目录,则 %cd% 返回的路径并不是批处理文件所在目录的路径,而是执行环境当前的路径。
%cd% 和 %~dp0 区别:
①使用范围上的不同
%cd% 可以在批处理脚本(bat脚本)、命令行窗口中使用;
%~dp0 只能在批处理脚本(bat脚本) 中使用;
②bat 脚本执行时,%cd% 代表的值会变化,因为代表的是当前目录;
%~dp0 代表的值不会变化,因为代表的是脚本文件在磁盘的位置。
联系客服