批处理脚本语言是微软Windows系统自带的原生开发语言,不需要任何环境构建就能执行的脚本。
应该注意的是,如果脚本中涉及中文(非ASCII字符)时,应将编码调整为ANSI,否则会乱码。
Hello world
@echo off
echo "hello world"
:: 暂停,屏幕上显示“请按任意键继续. . .”,一般用于脚本结束时给用户看执行结果
pause
:: 也可以 pause > nul,nul表示空文件,暂停时不会显示提示语
路径的表示方法
batch批处理脚本最重要的一个用途是处理文件和目录,往往出现在分支判断语句if-else中或循环语句for中。
Windows的路径不区分大小写,分隔符既可以是斜杠/
也可以是反斜杠\
。
样例 | 说明 |
---|---|
d:/1/2/3.txt |
绝对路径 |
./a.txt |
相对路径,. 表示工作目录 |
d:/1/2/*.txt |
通配符* 匹配文件名中的任意字符串 |
* |
单独的通配符表示工作路径下的所有文件 |
../ |
父目录 |
内部命令是系统内置的命令,可以通过help命令查看所有的内部命令。也可以通过command /?
的方式查看特定命令的用法。
常用的内部命令介绍如下:
命令 | 功能 | 更多介绍 |
---|---|---|
cd , chdir |
显示当前目录名或改变当前目录 | 变量%cd% 为当前工作路径 |
dir |
列出目录中的文件和子目录 | |
md , mkdir |
创建目录 | 可以创建多层目录 |
move |
移动或重命名文件或目录 | |
ren , rename |
重命名文件 | |
del , erase |
删除文件或目录 | |
rd , rmdir |
删除目录 | /s 可以删除目录树 |
copy |
复制 | 可以有多个源文件,但目标文件只能有一个 |
xcopy |
复制文件和目录树 | 功能选项比较多 |
robocopy |
高级复制工具 | 适用于需要高可靠性以及大量文件的场景 |
attrib |
显示或更改文件属性 | 可以给文件设置只读、隐藏等属性 |
命令 | 功能 | 更多介绍 |
---|---|---|
date |
显示或设置日期 | 变量%date% 为当前日期和星期 |
time |
显示或设置时间 | 变量%time% 为当前时间,精确到百分秒 |
start |
启动一个单独窗口以运行特定程序或命令 | 可以是一个程序、文件、网页等,系统会自动打开合适的程序 |
systeminfo |
显示系统信息 | |
tasklist |
显示所有进程和服务 | 可以设置显示的格式,并筛选需要的内容 |
ver |
显示windows版本 | |
diskpart |
配置磁盘分区 | 比带UI的磁盘管理功能强,需要管理员权限 |
recover |
从损坏的磁盘中恢复可读取的信息 | |
shutdown |
关机 | 可以设置重启或者定时等 |
命令 | 功能 | 更多介绍 |
---|---|---|
cmd |
打开另一个命令行窗口 | 可以设置新窗口的属性和行为 |
call |
调用批处理文件 | call [drive:][path]filename [batch-parameters] |
echo |
回显消息 | echo on/off 可启用或关闭命令回显,echo= 表示打印一个空行 |
exit |
退出 | 可以设置返回值errorlevel |
color |
设置默认控制台前景和背景颜色 | 只生效一次 |
title |
设置cmd窗口标题 | |
prompt |
更改 Windows 命令提示 | 即输入每一行命令时,前面C:\WINDOWS\system32> 的部分 |
cls |
清除屏幕 | 乱糟糟的屏幕确实很烦人 |
more |
逐屏显示输出 |
命令 | 功能 | 更多介绍 |
---|---|---|
type |
显示文本文件内容 | |
find |
搜索字符串 | 显示输入中含有特定字符串的行,常与管道符` |
findstr |
搜索字符串 | find 的升级版,功能更强大,能匹配简单的正则表达式 |
sort |
对输入进行排序 | 按行排序 |
tree |
用图形方式显示文件夹树 | |
comp |
比较两个文件区别 | 按照字节比较,适用于二进制文件 |
fc |
比较两个文本文件区别 | 适用于文本文件 |
外部命令会执行电脑中的某个程序,程序可能是系统预装的,也可能是用户安装的,如
常用的windows预装的外部命令基本是网络相关的程序,介绍如下:
命令 | 功能 | 更多介绍 |
---|---|---|
net |
(网络)管理指令 | 有很多功能,比如用户管理、服务管理、查询网络信息、共享资源管理等 |
ipconfig |
显示网络适配器信息 | |
ping |
测试网络连通性 | 有很多可选项 |
telnet |
连接远程端口 | 明文通信,注意安全 |
ssh |
远程加密连接 | |
ftp |
远程文件传输 | |
tracert |
路由追踪 | 显示本机到特定地址过程中经过的路由器IP地址 |
route |
显示路由表 | |
arp |
显示IP地址与MAC地址的映射关系 | |
nslookup |
查询域名的DNS信息 | |
reg |
注册表编辑器相关指令 |
set可以用于变量的赋值,显示等操作。此处变量又称作环境变量。环境变量的值全都是字符串。
Windows的环境变量名不区分大小写。
变量的取值需要在其前后加上百分号%
。
注意:set后面的赋值语句中不应带有任何多余的空格,Windows会将空格解释为变量或字符串的一部分。
:: 不带空格的情况
set aa=1
:: 下面一行输出"1"
echo %aa%
:: 带空格的情况
:: 变量名为"a ",值为字符串" 2"
set aa = 2
echo %aa %
:: 显示所有a开头的变量
set a
:: 删除变量,等号后面什么都不加
set aa=
:: 下面一行输出“环境变量 aa 没有定义”
set aa
交互式操作
set /p
表示从标准输入流读入一个字符串。
:: 将用户输入的字符串存入变量中
set /p a=
字符串比较
批处理命令中,字符串的比较是逐字比较编码的。windows的比较运算符比较特殊:
==
或equ
neq
gtr
geq
lss
leq
应当注意的是,==
的两边可以没有空格,但其他比较运算符需要空格分隔。
@echo off
set a=1234
set b=12245
if a gtr b echo a大于b
pause
可以用中括号把字符串括起来,该语法可以用来表示空字符串。
@echo off
set a=
if [%a%]==[] echo a是空字符串
pause
字符串拼接
@echo off
set a=hello
set b=world
:: c=hello world
set c=%a% %b%
echo %c%
pause
字符串截取
使用%变量名:~起始位置,截取长度%
来截取字符串,逗号和截取长度可省略,表示截取到末尾。起始位置可以用负数,表示倒数第几个。
@echo off
set a=1234567890
:: 截取前五个字符12345
set b=%a:~0,5%
:: 截取最后五个字符67890
set b=%a:~-5%
echo %b%
pause
字符串替换
使用%变量名:原子串=替换子串%
来进行字符串的部分替换。
@echo off
set a=hello Alice!
set b=%a:Alice=Bob%
:: b=hello Bob!
echo %b%
pause
使用set /a
执行算术运算。
基本的算术运算符都有:+
加、-
减、*
乘、/
除、%
取余、()
括号。
set /a (1+2)*9%5
:: 可以将算数运算的结果赋值给一个变量
set /a a=(1+2)*9%5
>
, >>
, <
可以输入输出数据流重定向,箭头方向表示数据的流向。
>
表示覆盖输出,>>
表示追加输出,<
表示输入。
:: 将字符串输出到文本文件,会覆盖原本的文件内容
echo hello world > a.txt
:: 将字符串追加输出到文本文件,内容会接在原本文件的末尾
echo hello world >> a.txt
:: 将文本内容作为指令的输入
sort < a.txt
&
, &&
, ||
,连接多条命令,根据前一条命令执行结果有不同的执行过程。
:: & 表示单纯的连接,连接起来的命令顺序执行,命令执行成功与否不影响后续命令的执行
:: && 表示:仅当前一条执行成功时,执行后面的命令
:: 下面一行不会输出"ok"
aaaa && echo "ok"
:: || 表示:仅当前一条执行失败时,执行后面的命令
:: 下面一行不会输出"ok"
echo "haha" || echo "ok"
|
将前一条命令的输出作为后一条命令的输入。常用于在大段输出之中进行过滤筛选操作。
:: 在进程列表中找到explorer的相关信息
tasklist | find /i "explorer.exe"
if-else
语句用于控制流的分支判断,如果语句返回true,则运行if后面的语句,返回false则运行else后面的语句。
该用法是if语句最基本的用法,配合字符串比较语句使用。
:: /I 表示不区分大小写
:: IF [NOT] [/I] string1==string2 command
@echo off
set a=123
:: 单行的if
if %a%==123 echo 只有if的情况可以不加括号
:: 单行的if-else
if %a%==123 (echo 需要用括号括起来) else echo 这里的括号可加可不加
:: 多行的if-else
if %a%==123 (
echo 可以跨行
echo 可以有多行语句
)else (
echo else关键字不能作为一行的开头
echo else与后面的括号之间需要有空格分开
)
pause > nul
非常常用。
:: IF [NOT] EXIST filename command
if exist d:\a.txt (echo 存在) else (echo 不存在)
windows会将命令执行的结果保存在变量%ERRORLEVEL%
中。
:: IF [NOT] ERRORLEVEL number command
:: 当上一条命令返回的错误码值大于或等于某个值的时候,将执行command操作
:: 一般情况下,成功执行返回0,非零值都是失败的情况
:: 等价于 IF %ERRORLEVEL% GEQ number command
@echo off
:: 下面一行copu不是一个命令,所以会执行失败,返回一个非0的错误码
copu a.txt bak/b.txt
echo errorlevel=%errorlevel%
if errorlevel 1 echo SUCCESS
pause
::%ERRORLEVEL%的一个用例
goto answer%ERRORLEVEL%
:answer0
echo Program had return code 0
:answer1
echo Program had return code 1
:: IF DEFINED variable command
if defined a (echo a被定义了) else a未被定义
for
语句用于执行循环控制流,脚本会遍历给定的集合,并执行循环体。循环体部分也可用括号实现多行语句。
batch脚本的循环语句功能较弱,如果要实现复杂的循环判断逻辑,建议使用
goto
语句。
FOR %variable IN (set) DO command [command-parameters]
最基本的用法,集合是字符串的集合,用英文逗号或者空格分隔。
此处的变量名只能用单一字母,且区分大小写,所以所以 %a 不同于 %A。
:: 如果是在批处理文件中使用for语句,那么应该双写百分号
FOR %%v IN (alice,bob,charlie) DO echo %%v
FOR [/d] %variable IN (path/*) DO command [command-parameters]
集合部分是一个带通配符的路径,此时系统会将路径匹配到对应目录下的文件。
添加/d
选项后,匹配对应目录下的子目录。
:: 匹配文件
FOR %%v IN (./path/*) DO echo %%v
:: 匹配子目录
FOR /d %%v IN (./path/*) DO echo %%v
应该注意的是,此处的循环变量会存储文件的绝对路径,如果要存储部分路径(如文件名、扩展名等),需要进行变量名扩展操作。扩展操作在for /?
中有详细介绍,此处仅介绍几个常用的扩展:
%~i
:删除引号%~di
:取盘符%~pi
:取盘符内的目录路径%~ni
:取文件名部分%~xi
:取扩展名部分%~ai
:取文件属性%~ai
:取文件日期/时间%~zi
:取文件大小将上述扩展组合使用可以得到复杂结果:
%~dpi
:仅取路径%i
的父目录部分%~nxi
:仅取路径%i
的文件名和扩展名部分:: 打印工作目录下所有文件名
FOR %%i IN (*) DO echo %%~nxi
:: 使用ffmpeg工具将目录下所有.ogg文件转换成.mp3文件
for %%v in (./*.ogg) do ffmpeg -i "%%~dpnxv" -ar 44100 -ab 320k -f mp3 -acodec libmp3lame -y "%%~dpnv.mp3"
FOR /R [[drive:]path] %variable IN (set) DO command [command-parameters]
检查以 [drive:]path
为根的目录树,指向每个目录中的 FOR 语句。如果在 /R
后没有指定目录规范,则使用当前目录。
系统会将目录树中每一个目录拼接上set中的每一项,构成一个新的路径(目录或文件),然后赋值给循环变量。如果set仅为一个单点.
字符,则枚举该目录树。
:: 给每个目录都匹配一个1.txt和2.exe
FOR /r ./path/ %%v IN (1.txt,2.exe) DO echo %%v
FOR /L %variable IN (start,step,end) DO command [command-parameters]
for循环最普通的用法。
:: 列举1~20的奇数
FOR /L %%v IN (1,2,20) DO echo %%v
FOR /F ["options"] %variable IN (file-set) DO command [command-parameters]
读取文件并按行赋值给循环变量,可以将每行进行拆分并设置多个变量进行承接
用法很复杂,详见for /?
,此处仅做简单介绍。
:: 读取文件并按行输出
FOR /f %%v IN (samlpe.txt) DO echo %%v
::
、rem
用于行注释,注释的内容不会被执行。
:: 这里是注释
rem 这里也是注释
@
用在一条命令的开头,使该命令不在屏幕上回显。
:: 大多数情况下就这一个用法
@echo off
:
用于标识和命名代码中的一个位置,goto
可以直接跳转到这个位置。一般需要和判断语句结合使用。
由于batch命令在变量和控制流处理方面非常的瘸脚,所以善用goto语句可以有效简化脚本。
:: 会跳过第二行的命令
goto sect2
echo "1"
: sect2
echo "2"
Windows 自带的文件搜索功能非常的垃圾,很多情况下可能根本搜不出东西来,因此不如直接写一个脚本来进行文件搜索。
@echo off
set searchtempfile=searchtempfile
: start
echo 请输入查询关键字:
set /p keyword=
echo=
echo 搜索进行中,请稍等……
echo=
for /r %%d in (.) do (
for %%f in ("%%d"/*) do echo %%~f >> %temp%\%searchtempfile%
)
findstr %keyword% %temp%\%searchtempfile%
del %temp%\%searchtempfile%
echo=
echo 查找完毕,请按任意键开始一次新的查找
pause > nul
cls
goto start
评论区