大家好,你们可以叫我凌,是个16岁的网络安全学习者。
我们今天来讲讲Windows的命令提示符当中的批处理脚本,废话不多说我们直接开始吧!
你的首个 .bat 文件
.bat 文件介绍
什么是 .bat 文件
-
.bat 是 批处理文件 的扩展名,它是个纯文本文件。
-
里面写的每一行,都是你平时在 CMD 窗口中手动敲过的命令。
-
当你双击或调用这个文件时,cmd.exe 会从上到下、逐行执行里面的命令。
为什么它算"程序"
因为它具备了程序最基本的能力:
按顺序做事(顺序执行)
根据条件做不同的事(条件判断,后面学 if)
反复做同一件事(循环,后面学 for 和 goto)
你现在写的每行脚本,都是在让计算机自动完成一系列操作,这正是自动化运维的起点。
创建你的首个 .bat 文件
第1步:新建文本文件
在桌面上或任意文件夹里,右键 → 新建 → 文本文档。
第2步:写入内容
复制下面这段代码(特别注意:保存时编码选 ANSI,否则中文乱码)
bash
@echo off
title 我的第一个批处理
color 0A
cls
echo ==============================
echo 欢迎来到批处理的世界
echo ==============================
echo.
echo 当前系统时间:%time%
echo 当前系统日期:%date%
echo.
echo 按任意键退出...
pause > nul
以下为以CMD命令做的演示,供参考:

第3步:重命名
把 text.txt 改名为 text.bat(如果看不到 .txt,需要勾选"显示文件扩展名")。
以下以命令提示符的方式进行演示,供参考:
bash
ren text.txt text.bat

第4步:运行
双击目标文件或使用CMD输入文件名并回车,即可查看效果。
bash
text.bat
运行后如下所示

程序命令分析
|------------------|-----------|--------------------------------------------------------------------------------------|
| 命令 | 作用 | 细节 |
| @echo off | 关闭命令回显 | 默认 CMD 会先把"命令原文"打印出来再执行结果,看着很乱。echo off 关掉这个行为,前面的 @ 让 echo off 本身也不显示。这是所有批处理的标准开头。 |
| title XXX | 修改窗口标题栏文字 | 运行后窗口左上角显示你指定的标题,不再是"命令提示符" |
| color 0A | 设置窗口颜色 | 第一位是背景色(0=黑),第二位是前景色(A=亮绿)。常用:0A 黑绿、0C 黑红、1E 蓝黄。 |
| cls | 清屏 | 把窗口里之前残留的内容清干净,给你个清爽的屏幕。 |
| echo ===== | 输出文字 | 把后面的内容原样打印到屏幕上。 |
| echo. | 输出空行 | echo 后面跟一个点(或冒号),会打印一个空白行,用来让排版更美观。 |
| echo 当前时间:%time% | 显示系统变量 | %time% 和 %date% 是系统自带的动态环境变量,会实时取出当前时间日期。 |
| pause > nul | 暂停执行 | 显示"按任意键继续...",脚本停在这里等用户按键。> nul 把提示文字藏起来,只保留停顿效果。 |
| rem 或 :: | 添加注释 | 在脚本里写说明文字,不会被执行。例如"rem 这是注释" 或 ":: 这也是注释"。 |
.bat 的执行方式
|-------------|------------------------|----------------------|------------------------|
| 方式 | 操作 | 特点 | 适用场景 |
| 双击 | 鼠标双击 .bat | 执行完自动关闭窗口(除非有 pause) | 最终用户使用 |
| 管理员身份运行 | 右键 → 以管理员身份运行 | 获得最高权限,可以修改系统目录和注册表 | 需要高权限的操作(如改 hosts、装服务) |
| 在 CMD 中手动调用 | 打开 CMD,输入 First.bat 回车 | 窗口不关闭,能看到所有输出和报错 | 开发调试阶段永远用这个 |
注意:写批处理时,建议先用 CMD 手动调用测试,完全没问题了再双击。如果直接双击而脚本又报错,窗口一闪而过,你根本看不到错误信息。
变量:让脚本拥有"记忆"
什么是变量?为什么需要它?
之前写 .bat,所有命令都是写死的。比如:
bash
echo 当前时间是:%time%
这里的 %time% 就是系统帮我们定义好的变量,它会动态变化。
变量的本质:在内存中开辟一个小格子,给它起个名字,存进去一个值,后面随时可以取出来用。
没有变量:你要处理 5 个文件名,就得手动改 5 次脚本。
有了变量:你只需改一次变量的值,脚本自动适应。
set 命令:定义、修改变量
基本的用法:设置一个变量
在 CMD 中(或 .bat 里)输入:
bash
set name=张三
echo %name%
运行结果:张三
如图所示:

拆解:
set 是命令关键字。
name 是变量名(你可以随便起,但建议见名知义)。
= 是赋值符号。
张三 是存入的值。
注意:等号两边不要有空格!写 "set name = 张三" 是错的,会导致变量名变成 "name "(带空格)。
当然,依照我们前面学习过的。也可以关闭回显使界面更加美观:
bash
@echo off
set name=张三
echo %name%

查看已有的变量
-
在 CMD 中直接输入 set 回车,会列出当前会话中所有的环境变量(非常多)。
-
想看特定的某个变量:set name,会显示所有以 name 开头的变量。
如图所示:


删除变量
bash
set name=
把变量赋值为空,就是删除它。之后再 echo %name% 只会显示 %name% 原文(因为变量不存在了)。

变量值的特殊性
在批处理中,所有变量默认都是字符串。哪怕你存的是数字,它也是文本。
bash
set num=123
echo %num%
输出是 123,但它本质是字符串 "123",不能直接做数学运算(后面会讲 set /a 来做运算)。
引用变量:%变量名%
引用变量的固定写法是:变量名前后各加个 "%"。
bash
set myfile=test.txt
echo 我要操作的文件是:%myfile%
copy %myfile% backup_%myfile%
第这样子第三行会变成:copy test.txt backup_test.txt。
记住:
设置变量用 set x=值(不加 %)
读取变量用 %x%(加 %)
交互式输入:set /p
这是非常有用的功能:脚本运行到一半,停下来问用户要信息。
语法:
bash
set /p 变量名=提示文字
示例:
bash
@echo off
set /p name=请输入你的名字:
echo 你好,%name%!
pause
运行效果:
请输入你的名字:张三
你好,张三!
/p 的含义:prompt(提示),等待用户输入并按下回车,把输入的内容存进变量。
如图所示:

数学运算:set /a
因为默认是字符串,所以要做加减乘除,必须加 /a 参数。
示例:
bash
@echo off
set /a num1=10
set /a num2=3
set /a result=num1 + num2
echo 10 + 3 = %result%
set /a result=num1 * num2
echo 10 * 3 = %result%
pause
输出:
10 + 3 = 13
10 * 3 = 30
支持的运算符:+(加)、-(减)、*(乘)、/(除)、%(取余)

注意:在批处理中取余要写成 "%%",在CMD中直接 set /a 10%%3 会报错,以下为解释供参考
1.在命令行窗口:取模运算使用单个 %,例如 set /a 10%3 就能正确计算 10 除以 3 的余数。
2.在批处理文件中:需要对 % 进行转义,使用两个连续的 %,即 %%。例如,在 .bat 脚本中要写 set /a num=4%%2。
% 在 CMD 里用来引用变量(如 %var%)。当你输入 10%%3 时:
CMD 优先寻找变量:它把第一个 % 和第二个 % 配对,试图解析它们之间的内容(这里是空或数字)作为一个变量名。
变量不存在:由于没有名为 10 或类似名称的变量,解析失败。
报错:最终,set /a 命令无法识别这个表达式,因此报错"缺少运算符"。
变量生效的时机
批处理在执行代码前,会预先将所有的 %变量% 替换成当时的值,然后再执行命令。这叫预处理。
请看下面这个脚本:
bash
@echo off
set num=1
if %num%==1 (
set num=2
echo 现在的num是:%num%
)
pause
大部分人的预期是输出 "现在的num是:2",但实际输出是 "现在的num是:1"。

原理讲解
因为 if 语句后面的括号 ( ) 里的内容,在被执行之前 %num% 就已经被替换成了最开始的 1。里面那个 "set num=2" 虽然确实修改了内存里的值,但 echo 语句里的 %num% 早在修改之前就"翻译"好了,不会再变。
解决方法
在脚本开头加上一行 "setlocal enabledelayedexpansion",然后引用变量时用 "!变量名!" 代替 "%变量名%"。
修正后的正确写法:
bash
@echo off
setlocal enabledelayedexpansion
set num=1
if %num%==1 (
set num=2
echo 现在的num是:!num!
)
pause
此时输出正确:现在的num是:2

> - 绝大多数情况下,用 %var% 就够。
> - 只有在 if 或 for 的括号 ( ) 内部修改变量并立即读取时,才需要加 setlocal enabledelayedexpansion 并用 !var!。
特殊变量:%~dp0 与相关变量
这是批处理中最常用、最实用的特殊变量,它的作用是:获取当前 .bat 脚本所在的文件夹路径。
%0 是什么
%0 代表脚本自身的完整路径和文件名。比如你的脚本放在 C:\test\my.bat,那么在脚本内部,%0 的值就是 C:\test\my.bat。
各种 %~ 扩展
在 %0 的基础上,加不同的符号可以提取路径的不同部分:
|--------|---------------------|----------------------------|
| 写法 | 含义 | 示例(假设脚本在 C:\test\my.bat) |
| %0 | 脚本自身的完整路径+文件名 | C:\test\my.bat |
| %~d0 | 只取盘符(d=drive) | C: |
| %~p0 | 只取路径(p=path,不含盘符) | \test\ |
| %~n0 | 只取文件名(n=name,不含扩展名) | my |
| %~x0 | 只取扩展名(x=extension) | .bat |
| %~dp0 | 盘符 + 路径(d+p) | C:\test\ |
| %~f0 | 完整的绝对路径(f=full) | 同 %0,但会规范化路径 |
为什么 %~dp0 如此重要
写脚本时,经常需要引用跟脚本放在同个文件夹里的其他文件。
错误的写法
bash
copy config.ini backup\
如果你在 C:\test 下双击脚本能正常找到 config.ini。但如果你在 C:\windows 下用绝对路径调用这个脚本(比如 C:\test\my.bat),那么当前工作目录是 C:\windows,脚本会去 C:\windows\config.ini 当中找,结果是根本找不到。
正确的写法
bash
copy "%~dp0config.ini" "%~dp0backup\"
这样无论你在哪里执行这个 .bat,它都会老老实实去找 自己所在文件夹 里的 "config.ini"
流程控制:if 和 goto
if 命令:让脚本做判断
if 的作用是:条件成立,就执行后面的命令。
字符串/数字比较:if 和 ==
最基本的用法是比较两个值是否相等。
语法:
bash
if 值1 == 值2 命令
示例:
bash
@echo off
set /p input=请输入 y 或 n:
if %input% == y echo 你输入了 y
if %input% == n echo 你输入了 n
pause
如图所示:

注意:
== 两边要有空格(固定写法)。
如果变量可能为空,或者包含空格,一定要加双引号,否则会报错。
安全写法(强烈推荐):
bash
if "%input%" == "y" echo 你输入了 y
数值比较
对于纯数字的比较,除了 ==,更专业的做法是用这些运算符(英文缩写):
|-----|-----------------|-----------|
| 运算符 | 含义 | 类比 C/JAVA |
| EQU | 等于 (Equal) | == |
| NEQ | 不等于 (Not Equal) | !=LSS |
| LSS | 小于 (Less) | < |
| LEQ | 小于等于 | <= |
| GTR | 大于 (Greater) | > |
| GEQ | 大于等于 | >= |
示例:
bash
@echo off
set /a score=85
if %score% GEQ 60 echo 及格了!
if %score% LSS 60 echo 不及格,继续努力。
pause

忽略大小写比较:/i 参数
用户可能输入大写 Y,也可能输入小写 y。加上 /i 就不区分大小写了。
bash
if /i "%input%" == "y" echo 你输入了 y(不分大小写)
检查文件/文件夹是否存在:if exist
这是运维和脚本中最常用的功能------先检查再操作,避免报错
语法:
bash
if exist 文件路径 命令
示例:判断 C:\test.txt 是否存在,存在就删除它。
bash
@echo off
if exist C:\test.txt (
echo 找到文件,正在删除...
del C:\test.txt
) else (
echo 文件不存在,跳过删除。
)
pause
如图所示(改进版):

else 子句
if 可以搭配 else 表示"否则"。
语法:
bash
if 条件 (
命令1
) else (
命令2
)
关键规则:
) 和 else 必须写在同一行。
else 和 ( 必须写在同一行。
错误的写法(会报错)
bash
if 条件 (
命令1
)
else (
命令2
)
这种写法 CMD 会把 if 在 ) 处结束,然后单独遇到 else,直接报 'else' 不是内部或外部命令。
带变量的复杂判断示例
bash
@echo off
setlocal enabledelayedexpansion
set /p num=请输入一个数字:
if !num! GTR 10 (
echo 你输入的数字大于 10
) else (
echo 你输入的数字小于或等于 10
)
pause
goto 命令:让脚本"跳起来"
goto 的作用是:让脚本的执行流程,直接跳转到脚本中指定的"标签"位置
标签的定义:":" + 标签名
在脚本的任意位置,另起一行,用冒号加名字定义一个标签。
bash
:start
echo 这里是开始
goto 的使用:无条件跳转
bash
@echo off
echo 第一步
goto skip_part
echo 第二步(这行永远不会被执行)
:skip_part
echo 第三步(跳到了这里)
pause
运行结果:
bash
第一步
第三步(跳到了这里)
中间的"第二步"被完美跳过。

死循环与逻辑结束
如果不加限制地 goto,脚本会跑飞。通常配合 if 使用。
也可以用 goto :eof 直接跳到文件末尾(结束脚本)。eof 是 End Of File 的缩写,是系统内置的特殊标签。
这里就不进行演示了,感兴趣的可私下研究。
综合实验
实验一:带有"记忆"和"容错"的智能计算器
目标:编写 Calculator.bat,实现一个无限循环的计算器菜单,直到用户选择退出。
代码示例:
bash
@echo off
title 计算器
setlocal enabledelayedexpansion
:menu
cls
echo ====== 计算器 ======
echo 1. 加法
echo 2. 减法
echo 3. 乘法
echo 4. 除法
echo 5. 退出
echo ====================
set /p choice=请输入选项 (1-5):
if "%choice%"=="1" goto add
if "%choice%"=="2" goto sub
if "%choice%"=="3" goto mul
if "%choice%"=="4" goto div
if "%choice%"=="5" goto exit
echo 无效选项,请重新输入!
pause
goto menu
:add
set /p num1=请输入第一个数字:
set /p num2=请输入第二个数字:
set /a result=num1+num2
echo 结果:%num1% + %num2% = %result%
pause
goto menu
:sub
set /p num1=请输入第一个数字:
set /p num2=请输入第二个数字:
set /a result=num1-num2
echo 结果:%num1% - %num2% = %result%
pause
goto menu
:mul
set /p num1=请输入第一个数字:
set /p num2=请输入第二个数字:
set /a result=num1*num2
echo 结果:%num1% * %num2% = %result%
pause
goto menu
:div
set /p num1=请输入被除数:
set /p num2=请输入除数:
if "%num2%"=="0" (
echo 除数不能为 0!
pause
goto menu
)
set /a result=num1/num2
echo 结果:%num1% / %num2% = %result%
pause
goto menu
:exit
echo 感谢使用,再见!
pause
exit
实验二:手工打造"计数器"实现批量创建文件夹
目标:编写 BatchCreator.bat,让用户输入一个数字(比如 5),然后自动创建 文件夹1、文件夹2 ... 一直到 文件夹5。
操作逻辑:
用 set /p 让用户输入要创建的数量(存入 total)。
定义计数器变量:set /a count=1。
定义一个标签 :loop。
在里面执行 md "文件夹!count!"(注意用 !count! 实时取值)。
执行 set /a count=count+1(计数器加 1)。
用 if !count! LEQ !total! goto loop(如果没达到总数,就跳回循环)。
最后输出"全部创建完成!"。
代码示例:
bash
@echo off
setlocal enabledelayedexpansion
:: 1. 让用户输入要创建的数量
set /p total=请输入要创建文件夹的数量:
:: 2. 定义计数器变量,初始为 1
set /a count=1
:: 3. 定义循环标签
:loop
:: 4. 判断当前计数是否小于等于总数
if !count! LEQ !total! (
:: 创建文件夹,使用 !count! 实时取值
md "文件夹!count!"
:: 计数器加 1
set /a count=count+1
:: 跳回循环继续判断
goto loop
)
:: 5. 循环结束,输出完成信息
echo 全部创建完成!
pause
实验三:脚本自检与配置文件生成器
目标:编写 CheckEnv.bat,实现一个"环境检测与修复"小工具。
要求:
-
脚本启动后,首先检查 脚本自己所在的目录 下,是否存在 config.ini 文件。
-
如果 不存在 config.ini,则自动创建一个。内容如下
System
Status=Ready
CreateTime=%date% %time%
代码示例:
bash
@echo off
setlocal
:: 获取脚本所在目录下的 config.ini 完整路径
set "configfile=%~dp0config.ini"
:: 检查文件是否存在
if exist "%configfile%" (
:: 存在:显示内容并提示
echo 配置文件已加载
echo ------------------------------
type "%configfile%"
echo ------------------------------
) else (
:: 不存在:创建文件并写入内容
echo 配置文件缺失,已自动重建!
(
echo [System]
echo Status=Ready
echo CreateTime=%date% %time%
) > "%configfile%"
)
:: 暂停以便查看结果
pause