0、前言:
0.1、从编程语言学习的四个维度审视批处理
数据结构:批处理没有现代意义上的数据结构,本质是纯文本 + 字符串处理,所谓 "数组" 是模拟出来的。仅支持变量、环境变量、参数、返回值(% errorlevel%)。
语法规则:批处理语法非常原始、怪异、容错差,核心规则是逐行执行,一行一条命令(可 & 连接),变量延迟扩展:setlocal enabledelayedexpansion + !var! 注释用rem 或 ::(后者在括号块内会出错),代码块用 ( ) 包裹,但语法敏感,换行、空格都可能报错。流程控制有if 判断、for 循环(最复杂、最强大)、goto 跳转、call 调用子程序、转义字符:^ 转义 & | > < ( 等。字符串操作通过截取、替换、拼接全靠内置语法,无函数。
批处理完全没有自主内存管理,由系统托管,变量存在进程环境块(PEB / 环境内存),不由脚本管理。批处理不是编译型,批处理是通过cmd.exe解释器执行的 → 调用系统 API / 外部命令 → 执行。执行外部命令时会创建子进程,执行完返回。
语言特性和编程范式:批处理是极其受限的过程式脚本语言,几乎不支持现代范式。弱类型、无类型系统,无函数(只有 :label + call 模拟子程序),无递归深度保障,无异常处理,只有 %errorlevel% 判断返回码,极强的系统调用能力:文件、注册表、网络、进程管理都靠外部命令,天生面向系统自动化、批量任务 。批处理是过程式编程,面向命令(一切都是 "执行命令"),本质是系统外壳胶水语言,不是通用编程语言。
0.2、这篇文章重点
基础补充
1、批处理中&和&&的区别
命令1 & 命令2 & 命令3 表示依次执行性三条命令,不论前面的命令执行成功还是失败,都执行后一条,&&是只有在前面成功之后,才执行后面的命令。
2、批处理中for命令中的/f参数:
批处理里,只有 for /f 才有 "文本切割、截取、提取" 的功能,所以只是执行一条命令,也要用for。
for /F = 解析 / 读取循环(File)
2.1、命令样式
bash
复制代码
for /f "选项" %%i in (文件名/命令/字符串) do 命令
2.1、常用选项说明
bash
复制代码
delims=指定分隔符,默认是空格、Tab。比如 delims=, 表示按逗号切分。
tokens=指定取第几列数据。tokens=1 取第 1 列tokens=1,3 取第 1、3 列tokens=1-5 取 1~5 列
skip=n跳过前 n 行,常用于跳过标题行。
2.2、案例
bash
复制代码
@echo off
for /f "tokens=1-3 delims=-/. " %%a in ("%date%") do (
set "year=%%a"
set "month=%%b"
set "day=%%c"
)
echo year: %year%
echo month: %month%
echo day: %day%
pause
2.3、补充
bash
复制代码
echo 【内存信息】
for /f "tokens=2 delims==" %%a in ('wmic computersystem get TotalPhysicalMemory /value') do set memB=%%a
set /a memGB=memB / 1073741824
echo 物理内存:!memGB! GB
echo.
rem for /f : 读取文本、解析命令输出,常见写法:for /f "tokens=2 delims==" %%a in ('命令') do ...
rem 作用是执行一条命令 → 拿到输出文本 → 按符号切割 → 取出你要的那一段
rem "tokens=2 delims=="表示用 = 作为分隔符,把一行切成两段,取第2段
rem 总结 for /f "tokens=段数 delims=符号" %%a in ('某条命令') do ...:先执行引号里的命令,拿到输出的每一行文本,按某个符号切割,取其中的第n段,给到%%a。
3、批处理中for命令中的/l参数:
专门用来循环数字,比如从 1 数到 10,从 0 数到 100。
for /L = 数字循环(Loop)
3.1、命令样式
bash
复制代码
for /L %%变量 in (起始值,步长,结束值) do 命令
3.2、案例
bash
复制代码
for /L %%i in (1,1,5) do echo %%i
bash
复制代码
@echo off
setlocal enabledelayedexpansion
set "output="
for /L %%i in (1,1,5) do set "output=!output! %%i"
echo 结果:%output%
4、批处理中条件中只有两种类型的值的比较,写法总结如下:
4.1、数字比较:
数字比较中 equ 等于 (equal)
数字比较中 gtr 大于 (greater than)
数字比较中 lss 小于 (less than)
数字比较中 geq 大于等于 (greater or equal)
数字比较中 leq 小于等于 (less or equal)
数字比较中 neq 不等于 (not equal)
4.2、字符串比较
字符串比较中 neq 不等于 (not equal)
字符串比较中 == 等于 (equal)
5、批处理中两种条件语句的写法:
批处理条件判断中条件的标准写法:if "%变量%" 比较符号 "内容"
因为批处理中可能还有数字的比较,这种写法就不用加双引号了:if %变量% 比较符号 内容
注意区分if中写条件和set中给变量赋值的区别:set "var=内容" ,加了参数/p和参数/a的,也可以加在后面给表达式整体加双引号。
6、批处理 | 和 || 核心区别
| 管道符的作用:把左边命令的输出,传给右边命令当输入
|| 容错或符作用:左边命令执行失败,才执行右边,对比&&,左边执行成功才执行右边。
小结:
& :不管成败,前后都执行
| :管道传输出给下一条命令
&&:左边成功,才执行右边
||:左边失败,才执行右边
7、批处理中标签书写规范以及goto和call的区别
批处理中不论是goto的标签还是call的标签,标签不能写在if或者for的模块当中,这是一种默认书写规范!
批处理中给goto用的标签也可以给call用,goto 不回头,call 会返回。
文件和文件夹相关:
1、批处理文件和文件夹基础:
1.1、批处理文件路径变量:
%~dp0 :只在批处理(.bat/.cmd)里有用,是专门用来拿「当前这个 bat 文件所在目录」的内置语法。其实就是位置参数的拓展,其中~表示去除引号,dp参数表示路径,%0表示当前文件的文件名。
1.2、删除文件和文件夹
删除文件:del 文件名
删除文件夹:rmdir 文件夹名
2、用批处理给文件夹换图标:
2.1、代码
bash
复制代码
@echo off
chcp 65001 >nul
echo 正在设置文件夹图标为海绵宝宝...
echo [.ShellClassInfo] > desktop.ini
echo IconFile=E:\C++Learn\batch_do\hai_mian_baobao.ico >> desktop.ini
echo IconIndex=0 >> desktop.ini
attrib +s "%cd%"
attrib +h +s desktop.ini
echo 搞定!刷新就能看到海绵宝宝图标啦
pause
2.2、相关知识
只要文件夹里有一个叫 desktop.ini 的文件,并且里面写了[.ShellClassInfo],系统就知道:这个文件夹要自定义显示!desktop.ini = 文件夹的 "外观配置单",[.ShellClassInfo] = 标记:我要改图标 / 文件夹信息。
IconFile= 的意思就是:文件夹图标 = 后面这个 .ico 文件。
一个ICO 文件里可能包含 多个尺寸图标(16×16、32×32、256×256),IconIndex=0 意思是:用第 0 个(第一个)图标。
普通文件夹 → 不读取 desktop.ini,加了 系统属性(+s) 的文件夹 → 才会读取 desktop.ini。
+h = 隐藏desktop.ini文件(不让你看见,避免误删),+s = 把desktop.ini标记为系统文件。
总结:Windows 资源管理器,并不是 "智能识别" 你要改图标,而是严格按照一套固定规则去读取配置。文件夹里要有 desktop.ini,里面要写图标路径,文件夹必须标记为 系统文件夹 (+s),配置文件要隐藏且系统属性 (+h +s)。就是说,可以自己建一个文本文档,叫desktop.ini,然后在里面写上这些东西,不通过批处理,通过手动操作的方式改文件夹图标,但是给文件夹和desktop.ini加属性还是要在cmd中进行。
3、批处理给文件创建快捷方式
3.1、代码
bash
复制代码
@echo off
chcp 65001 >nul
::===================== 你只改这里 =====================
:: 【你要给哪个文件创建快捷方式?】
set "TARGET_FILE=for_f_data.bat"
:: 【快捷方式要生成到哪里去?】(这里可以随便写路径)
set "SAVE_PATH=C:\Users\用户名\Desktop\我的快捷方式.url"
:: 创建一个变量,名字叫 SAVE_PATH,变量的值 = 一个文件路径
::=====================================================
:: 核心代码(不用动)
echo [InternetShortcut] > "%SAVE_PATH%"
:: echo 内容 > 变量存放的文件路径,本质就是把这个内容写入到文件中。
:: 本质就是echo [InternetShortcut] > C:\Users\xxx\Desktop\我的快捷方式.url
echo URL=file:///%~dp0%TARGET_FILE% >> "%SAVE_PATH%"
echo 快捷方式已创建到:%SAVE_PATH%
pause
3.2、相关知识
在 Windows 里,用 .url 这种方式创建快捷方式,本质就是:新建一个文本文件,后缀名改成 .url,里面写上固定格式的配置:[InternetShortcut] + 关联文件路径。系统看到这个文件,就把它当成快捷方式。
写成 file:///,Windows 才知道这是本地电脑里的文件。file: 表示 "本地文件协议",/// 固定格式(表示本地本机,不是网络电脑)。
\\ip = Windows 局域网路径,file:/// = 本地文件 URL 格式,file://ip = 局域网文件 URL 格式。
4、文本文件相关批处理操作
4.1、文本文件中指定内容替换
关键知识:批处理内置字符串替换,可以把变量里所有 aaa 换成 bbb。
范式:!变量名:查找内容=替换内容!
代码
bash
复制代码
@echo off
setlocal enabledelayedexpansion
set "oldStr=12345"
set "newStr=09876"
set "txtFile=ab.txt"
:: 遍历每一行
for /f "delims=" %%a in (%txtFile%) do (
set "line=%%a"
:: 替换本行内容
set "line=!line:%oldStr%=%newStr%!"
:: 写入临时文件
echo !line! >> temp.tmp
)
:: 覆盖原文件
move /y temp.tmp %txtFile% >nul
echo 替换完成
pause
结果:
4.2、文本文件之前插入内容
在文本之后插入内容可以用:>>,那么该如何在文本之前插入内容?
move命令:move [选项] 源文件/源文件夹 目标路径/目标文件名,作用是文件从原来的地方消失,跑到新的地方去了,相当于你在电脑上剪切文件,再粘贴到别的地方。例如move /y temp.tmp ab.txt执行完之后,temp.tmp 就没了,只剩下 ab.txt。
代码
bash
复制代码
@echo off
setlocal enabledelayedexpansion
:: 要处理的文件
set "file=ab.txt"
:: 要插入到【开头】的内容
set "insert_content=我是插入到最前面的内容"
:: 第一步:先写插入的内容到临时文件
echo %insert_content% > temp.tmp
:: 第二步:把原文件内容追加到后面
type "%file%" >> temp.tmp
:: 第三步:覆盖原文件
move /y temp.tmp "%file%" >nul
echo 已在文件开头插入内容!
pause
结果
补充copy命令:copy [选项] 源文件 目标路径/目标文件名,作用是原文件还在,同时生成一个一模一样的副本,相当于你在电脑上复制文件,再粘贴到别的地方。例如copy a.txt D:\,就是把 a.txt 复制一份到 D:\ 盘,原文件 a.txt 还在原地。