参考资料
常用语句
Windows 系统的批处理文件扩展名为 .bat 或 .cmd,通过 Cmd.exe 逐行解释执行,对大小写不敏感
C:\AUTOEXEC.BAT 在系统启动时会自动运行,可以将每次启动时都要运行的命令放入该文件中
脚本配置
1
2
3
4
|
@echo off :: 隐藏命令回显
chcp 65001 >nul :: UTF-8编码(静默设置)
title 我的脚本 :: 窗口标题
color 0A :: 黑底绿字(可选)
|
路径操作
1
2
3
4
|
%~dp0 # 批处理文件所在目录
cd %~dp0 # 进入批处理文件目录
cd %~dp0bin\ # 进入 bin 子目录
cd /d "C:\Program Files" :: 切换驱动器并进入目录
|
其中 d 为 Drive 的缩写,即为驱动器,磁盘;p 为 Path 缩写,即为路径,目录
1
2
3
|
%~nx0 :: 文件名和扩展名
%~1 :: 去掉引号的第一个参数
%~f1 :: 第一个参数的完整路径
|
重定向
1
2
3
4
|
>nul :: 丢弃标准输出
2>nul :: 丢弃错误输出
>nul 2>&1 :: 将所有输出都丢弃
>> file.log :: 追加到文件
|
变量操作
系统变量
1
2
3
|
echo 系统根目录: %SystemRoot% :: C:\Windows
echo 临时目录: %temp% :: 临时文件夹路径
echo 用户名: %username% :: 当前用户
|
自定义变量
1
2
3
|
set name=张三
set /a age=20+1 :: 算术运算
set /p input=请输入: :: 用户输入
|
参数处理
参数下标从 1 开始,通过百分号加数字表示
1
|
call test.bat "hello" "haha"
|
1
2
3
4
5
6
|
::test.bat
echo %1 ::"hello",对应传入的第一个参数
echo %2 ::"haha"
echo %0 ::脚本名 test.bat
echo %19 ::"hello"9
echo %* ::所有参数
|
字符串处理
截取字符串
1
2
3
4
5
|
set str=HelloWorld
echo 前5位: %str:~0,5% :: Hello
echo 第3位开始: %str:~2% :: lloWorld
echo 倒数第3位开始: %str:~-3% :: rld
echo 第2到倒数第2: %str:~1,-1% :: elloWorl
|
替换字符串
1
2
3
4
5
|
set str=hello world
echo %str%
:: 将 world 替换为 bat
set str=%str:world=bat% :: "hello bat"
|
字符串长度
通过循环获取字符串长度
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
::函数定义和初始化
::定义一个名为 strlen 的标签(函数),接受两个参数
:strlen <result> <string>
::启用延迟变量扩展,允许在代码块中使用 !var!
setlocal enabledelayedexpansion
::将第二个参数(要去掉引号)赋值给 str 变量,^ 防止特殊字符被解释
(set ^str=%~2)
::空字符串检查
::如果输入字符串为空,将结果变量设置为 0 并退出函数
if "!str!"=="" (
set "%~1=0"
exit /b
)
::初始化长度
set /a len=0
:loop
::主循环,如果当前字符串长度为空,则使用 endlocal 结束局部环境,将长度值传递给调用者,然后退出
if "!str!"=="" (
endlocal & set "%~1=%len%"
exit /b
)
::否则长度加 1,移除字符串的第一个字符,继续循环
set /a len+=1
set "str=!str:~1!"
goto loop
|
使用方法
1
2
|
call :strlen length "Hello World"
echo 字符串长度是: %length%
|
流程控制
条件判断
1
2
3
4
5
6
7
8
9
|
:: 字符串比较
if "%var%"=="value" (echo 相等)
:: 数值比较
if %number% gtr 100 (echo 大于100)
:: 文件检查
if exist "file.txt" (echo 文件存在)
if not defined var (echo 变量未定义)
|
1
2
3
4
5
6
7
|
if "%1"=="hello" (
echo 参数是hello
) else if "%1"=="world" (
echo 参数是world
) else (
echo 未知参数
)
|
1
2
3
4
5
6
7
8
9
|
:: ❌ 错误的写法(常见误区)
if errorlevel 1 echo 错误1
if errorlevel 2 echo 错误2
if errorlevel 3 echo 错误3
:: ✅ 正确的写法(必须从大到小)
if errorlevel 3 echoecho 错误3
if errorlevel 2 echo 错误2
if errorlevel 1 echo 错误1
|
若错误码 errorlevel(或称返回码)等于指定的数字,则条件成立,运行指定命令,否则跳过,运行下一句
if errorlevel n 的意思是"如果错误级别 大于等于 n",所以返回值必须按照 从大到小 的顺序排列
| 运算符 |
描述 |
替代写法 |
| EQU |
等于 |
== |
| NEQ |
不等于 |
if not 1==1 |
| LSS |
小于 |
|
| LEQ |
小于或等于 |
|
| GTR |
大于 |
|
| GEQ |
大于或等于 |
|
循环结构
基本格式: for [参数] %%变量 in (集合) do (命令)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
:: 显示当前目录下bat或txt文件
for %%i in (*.bat *.txt) do (echo %%i)
:: 递归显示E盘test目录下文件
for /r E:\test %%i in (*.txt *.bat) do (echo %%i)
:: 显示包含e或i的目录名
for /d %%i in (*e* *i*) do (echo %%i)
:: 递归遍历所有文件
for /r %%i in (*) do (echo %%i)
:: 数字序列1-5
for /l %%i in (1,1,5) do (echo %%i)
|
1
2
3
4
5
6
7
8
9
10
11
12
13
|
:: 解析日期
for /f "tokens=1-3 delims=-/. " %%j in ('Date /T') do echo %%j年%%k月%%l日
:: 读取文件内容
for /f "delims=" %%i in (zhidian.txt) do (echo %%i)
:: 去除每行前8个字符
setlocal enabledelayedexpansion
for /f %%i in (zhidian.txt) do (
set atmp=%%i
set atmp=!atmp:~8!
if {!atmp!}=={} (echo.) else (echo !atmp!)
)
|
跳转标签
1
2
3
4
5
6
7
8
9
10
11
12
13
|
:: 简单跳转
goto :label
:: 条件跳转
if errorlevel 1 goto :error
:: 函数式跳转
call :function_name
exit /b
:function_name
echo 这是一个函数
exit /b 0
|
指定跳转到 label 标签行,找到标签行后,程序将处理从 下一行开始 的命令
label 标签的名字最好是有意义的,字母前必须加个 冒号 : 来表示这个字母是标签
经常与 if 配合使用,根据不同的条件来执行不同的命令组
程序调用
调用其他批处理
调用 另一个 批处理程序,并且 不终止 当前的父批处理程序
如果不用 call 而直接调用别的批处理文件,那么执行完那个批处理文件后 将无法返回 当前文件并执行当前文件的后续命令
无法在脚本或批处理文件外使用 call
1
2
|
call other.bat arg1 arg2 # 调用后会返回
other.bat arg1 arg2 # 调用后不返回
|
启动外部程序
调用外部程序,所有的 DOS 命令 和 命令行程序 都可以由 start 命令来调用
1
2
|
start "C:\Program Files\app.exe" arg1 arg2
start /min e:\"program files"\notepad.exe # 开始时窗口最小化
|
文件路径名有空格时,就利用双引号
实用技巧
用户交互
1
2
3
|
:: 简单输入
set /p choice=请选择(Y/N):
if /i "%choice%"=="Y" goto yes
|
1
2
3
4
5
|
:: 选项选择
choice /c ync /m "确认执行吗"
if errorlevel 3 goto cancel
if errorlevel 2 goto no
if errorlevel 1 goto yes
|
choice 命令可以让用户输入一个字符(用于选择),从而根据用户的选择返回不同的 errorlevel(choice 的返回值是环境变量 errorlevel 的值)
然后配合 if errorlevel 选择运行不同的命令
并且限定用户只能输入"y"、“n”、“c"这三个选项中的一个
当你选择 y 时,y 是第 1 个选项,所以 errorlevel 的值为 1
当你选择 n 时,n 是第 2 个选项,所以 errorlevel 的值为 2
当你选择 c 时,c 是第 3 个选项,所以 errorlevel 的值为 3
进程管理
1
2
3
4
5
6
|
:: 结束进程
taskkill /f /im notepad.exe >nul 2>&1
:: 检查进程是否存在
tasklist /fi "imagename eq notepad.exe" | find "notepad.exe" >nul
if errorlevel 1 (echo 进程不存在) else (echo 进程运行中)
|
/f 参数表示强制终止进程,即无需提示用户确认即可终止进程
/im 参数后面跟着的是进程的映像名称(Image Name),用于指定要终止的进程
在命令中的 ??? 部分需要替换为具体的进程映像名称,例如 notepad.exe 或 chrome.exe
使用 taskkill 命令终止进程需要管理员权限
示例模板
基础脚本模板
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
@echo off & chcp 65001 >nul
title 批处理脚本 - %~n0
echo [INFO] 脚本启动时间: %date% %time%
echo [INFO] 工作目录: %cd%
:: 参数验证
if "%~1"=="" (
echo [ERROR] 缺少参数
echo 用法: %0 ^<参数^>
pause
exit /b 1
)
call :main %*
goto :eof
:main
echo 主逻辑开始...
:: 业务代码在这里
echo 主逻辑结束...
exit /b 0
|
菜单驱动脚本
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
@echo off
:menu
cls
echo ============ 主菜单 ============
echo 1. 备份文件
echo 2. 清理临时文件
echo 3. 系统信息
echo 0. 退出
echo.
choice /c 1230 /n /m "请选择:"
goto option%errorlevel%
:option1
echo 执行备份...
goto menu
:option2
echo 清理临时文件...
goto menu
:option3
systeminfo | findstr /c:"OS 名称" /c:"系统类型"
pause
goto menu
:option4
exit /b 0
|
调试技巧
1
2
3
4
5
6
7
8
9
10
11
12
13
|
:: 启用变量延迟扩展
setlocal enabledelayedexpansion
:: 调试输出
echo [DEBUG] 变量值: !var!
echo [DEBUG] 当前目录: %cd%
:: 暂停查看,屏幕上显示 `Press any key to continue...` 的提示,等待用户按任意键后继续
pause
:: pause 命令会使程序挂起
:: 记录日志
echo %date% %time% - 操作完成 >> script.log
|
在批处理中,变量默认是在 一行命令解析前 就被替换了
启用延迟扩展后,可以使用 !var! 来在命令执行时动态获取变量值
-
为什么需要延迟?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
:: 没有延迟扩展的问题
set count=0
for /l %%i in (1,1,5) do (
set /a count+=1
echo %count% :: 这里永远显示0!
)
:: 使用延迟扩展的正确方式
setlocal enabledelayedexpansion
set count=0
for /l %%i in (1,1,5) do (
set /a count+=1
echo !count! :: 这里会正确显示1,2,3,4,5
)
|
1
2
|
rem 这是注释
:: 这也是注释(更常用)
|
1
2
3
4
5
|
:: 批处理中使用 ^ 换行
echo 这是一段很长的文本,^
现在换行了
:: Shell脚本中使用 \ 换行
|
1
2
|
命令名 /?
:: 例如: ping /?
|
错误处理
1
2
3
4
5
6
|
:: 检查命令是否成功执行
some_command >nul 2>&1
if errorlevel 1 (
echo [ERROR] 命令执行失败
exit /b 1
)
|