语法
关键字
::
、rem
等为注释 ^1title=我的标题
设置cmd窗口标题(乱码时,需要将文件记事本打开另保存为ANSI)echo [message]
表示显示此命令后的字符echo on/off
表示在此语句后所有运行的命令都是否显示命令行本身(@echo off
关闭命令显示)pause
运行此句会暂停批处理的执行并在屏幕上显示Press any key to continue…的提示,等待用户按任意键后继续call [drive:][path]filename [batch-parameters]
调用另一个批处理文件(如果不用call而直接调用别的批处理文件,那么执行完那个批处理文件后将无法返回当前文件并执行当前文件的后续命令)%[1-9]
表示参数,%0
表示批处理命令本身exit
关闭窗口- 符号
+
COPY命令文件连接符* ?
文件通配符""
字符串界定符,其中的变量可正常解析|
命令管道符< > >>
文件重定向符@
命令行回显屏蔽符,如脚本中@echo 1
会隐藏命令不显示与屏幕上/
参数开关引导符:
批处理标签引导符%
批处理变量引导符^
转义字符 eg:if 1=1 (echo hello^(你好^)) else (echo bye)
setlocal enabledelayedexpansion
启用变量延迟模式,变量通过!myVar!
获取,使用!xx!
必须开启变量延迟 ^3- 批处理读取命令时是按行读取的(另外例如for命令等,其后用一对圆括号闭合的所有语句也当作一行),在处理之前要完成必要的预处理工作,这其中就包括对该行命令中的变量赋值
- 如下文案例,批处理在运行到这句“set a=5&echo %a%”之前,先把这一句整句读取并做了预处理——对变量a赋了值,那么%a%当然就是4了
而为了能够感知环境变量的动态变化,批处理设计了变量延迟。简单来说,在读取了一条完整的语句之后,不立即对该行的变量赋值,而会在某个单条语句执行之前再进行赋值,也就是说“延迟”了对变量的赋值
1
2
3
4:: 不开启变量延迟,结果为4,开启之后结果为5
:: setlocal enabledelayedexpansion
set a=4
set a=5&echo %a%
- 批处理读取命令时是按行读取的(另外例如for命令等,其后用一对圆括号闭合的所有语句也当作一行),在处理之前要完成必要的预处理工作,这其中就包括对该行命令中的变量赋值
变量
- 参考 ^2
- 设置变量:
set 变量名=变量值
set NAME=%NAME_TMP%
基于变量赋值时不用添加双引号,否则变量字符串会携带双引号
- 取消变量:
set 变量名=
- 展示变量:
set 变量名
- 列出所有可用的变量:
set
- 计算器:
set /a 表达式
,如set /a 1+2*3
输出7
控制语句
if语句
if [not] string1 == string2
if [not] %errorlevel% == 0
如果最后运行的程序返回一个等于或大于指定数字的退出编码则返回true%errorlevel%
这是个系统变量,返回上条命令的执行结果代码。0
表示成功,1-255
表示失败
if [not] exist filename
如果指定的文件名存在if [/i] string1 compare-op string2
- 参数
/i
表示不区分大小写 - compare-op
equ
等于neq
不等于lss
小于leq
小于或等于gtr
大于geq
大于或等于
- 参数
if defined variable
判断变量是否存在
1 | rem ======================= 示例1 ======================= |
for语句
FOR %variable IN (set) DO command [command-parameters]
在cmd窗口中,for之后的形式变量 i 必须使用单百分号引用,即 %i;而在批处理文件中,引用形式变量i必须使用双百分号,即 %%i ^4- for /f (delims、tokens、skip、eol、userbackq、变量延迟)
- tokens 提取列
- for /r (递归遍历)
- for /d (遍历目录)
- for /l (计数循环)
1 | :: 显示C盘根目录下所有非隐藏、非系统属性文件 |
函数
- 定义:函数以
:函数名
开头,以goto:eof
结尾 - 调用:
call:函数名 [参数1,参数2,…]
1 | call:myFuncName |
字符串操作
1 | :: 拼接 |
文件和文件夹操作
1 | # 输出123456至0.txt并覆盖原先文字 |
- 获取脚本目录,获取上级目录
1 | :: 获取脚本目录 |
常用命令
- 命令参数使用
/
标注,如help /?
- 如果命令参数后是路径,则必须是是右斜杠(使用左斜杠会找不到路径),和参数标识符区分
help
查看帮助help /?
查看help命令的帮助tasklist
列举进程(进程名太长则可能显示不全)/fo <table|csv|list>
显示结果格式。tasklist /fo csv
以cvs格式显示结果,可以将进程名显示完全
taskkill
taskkill /pid -f 10021
-t
结束该进程-f
强制结束该进程以及所有子进程/im
指定要终止的进程的图像名,如taskkill /F /IM notepad.exe
certutil -hashfile D:\test.txt MD5
(默认是SHA1) 计算文件的MD5值(linux是 md5sum)
结合PowerShell
- bat脚本(只能通过CMD运行)调用PowerShell脚本
1 | @echo off |
PowerShell脚本
- 简介
- 脚本以
.ps1
结尾;设置脚本默认powershell打开(可找到执行程序%SystemRoot%\system32\WindowsPowerShell\v1.0\powershell.exe
进行设置) PowerShell ISE
是Windows自带的PS脚本编辑器
- 脚本以
- test.ps1
1 | # 单行注释用#表示,多行注释用<#……#>表示 |
结合VBS
- 参考vbs.md
- bat优缺点
- 如本身没有延时函数,无法执行telnet等命令到达期望效果,此时可使用vbs
- 但是如移动、删除文件、复制文件夹、修改注册表等只用vbs就很容易出错,用bat却不怕出错
- bat和vbs互相调用举例
1 | # bat文件中调用vbs |
- bat传递参数到vbs
- bat中应该打印1、2、3、4、5,此时传入到vbs后会将3替换成test
- 参考:http://www.bathome.net/thread-27675-1-1.html
1 | ' 2>nul 3>nul&cls&@echo off |
执行telnet命令案例
1 | title=install-plugins |
常用脚本
零散(如java程序控制)
- 运行java
- 此时配置文件应和jar包位于同一目录
- 如果
set MY_PROJECT_HOME=%~p0..\
则表示设置bat文件所在目录的的上级目录为项目根目录 - 如果不是系统默认jdk,可将
%JAVA_HOME%
换成对应的路径
1 | chcp 65001 |
- 停止进程(此脚本停止java等进程不是很友好,netstat查询出的端口可能很多)
1 | chcp 65001 |
- 停止java进程
1 | REM 复制一个java.exe到项目jar包目录,并重名为java-test.exe,每个启动的jar必须拥有唯一的名称 |
后台运行bat文件
bat语法运行。缺点:执行
start xxx.exe
后,bat脚本窗口关闭了,但是exe执行程序弹框无法关闭(可使用RunHiddenConsole.exe)1
2
3
4
5
6@echo off
if "%1" == "h" goto begin
mshta vbscript:createobject("wscript.shell").run("%~nx0 h",0)(window.close)&&exit
:begin
:: 这是注释,后面运行脚本,如:
java -jar my.jar使用
RunHiddenConsole.exe
。需要将其加入到PATH或放在bat的同级目录,如下示例。RunHiddenConsole下载地址1
2
3
4:: 启动脚本 start_php_cgi.bat(直接执行php-cgi.exe默认监听端口是9000)
@echo off
echo Starting PHP FastCGI...
RunHiddenConsole.exe d:\software\xampp\php\php-cgi.exe -b 127.0.0.1:19000 -c d:\software\xampp\php\php.ini启动示例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17@echo off
setlocal
if exist start.bat goto ok
echo start.bat must be run from its folder
goto end
:ok
:: start /b 启动应用程序时不必打开新的命令提示符窗口。除非应用程序启用 CTRL+C,否则将忽略 CTRL+C 操作。使用 CTRL+BREAK 中断应用程序
:: CTRL+BREAK按键. 键位标识PS:PrtSc SysRq,SL:Scroll Lock,PB:Pause Break
start /b bin\test.exe >> log\console.log 2>&1 &
echo start successfully
:end
获取脚本参数。
test.bat
内容如下。运行test a.txt b.txt
则%1表示a.txt,%2表示b.txt1
2
3@echo off
type %1
type %2获取键盘输入
1
2
3
4
5
6
7
8@echo off
:: 后面的语句也可不加双引号
set /p QQ="Input you QQ number ......"
echo Your QQ number is %QQ%.
:: 取消变量QQ的定义
set QQ=
pause
`获取当前时间
1
2
3
4
5
6
7
8
9:: %date% => 2022/09/25 周日 %time% => 10:05:55.19
:: set YYYYMMDD=%date:~0,4%%date:~5,2%%date:~8,2%
:: 如果小于10点,小时是一个空格+点数,后面通过字符串替换掉空格
:: set hhmmss=%time:~0,2%%time:~3,2%%time:~6,2%
set DATETIME=%date:~0,4%%date:~5,2%%date:~8,2%%time:~0,2%%time:~3,2%%time:~6,2%
set DATETIME=%DATETIME: =0%
set "filename=bak_%DATETIME%.zip"
:: bak_20181016170530.zip
echo %filename%脚本示例
进入到当前目录、设置环境变量
%~dp0
%0代表批处理本身;~dp是变量扩充,d扩充到分区,p扩充到路径1
2
3
4
5
6
7rem 设置临时环境变量oracle_home为当前bat文件所在目录(%~dp0)下的Oracle64目录
set oracle_home=%~dp0\Oracle64
rem 进入到当前目录
%~d0
cd %~dp0
rem 运行exe文件
start plsqlDev.exe
oracle工具箱脚本
1 | :: ======================================== |
mysql数据库备份
- 设置定时任务参考windows.md#任务计划(定时任务)
1 | @echo off |
oracle数据库备份
- 设置定时任务参考windows.md#任务计划(定时任务)
1 | @echo off |
参考文章