Keil工程深度清理:批处理脚本自动化删除编译中间文件
1. 项目概述为什么我们需要一个“工程清洁工”在嵌入式开发尤其是使用Keil MDK这类IDE进行STM32、ARM Cortex-M等项目开发时每次编译、调试后工程目录里总会留下一大堆中间文件和临时文件。这些文件比如.o、.lst、.map、.dep对于最终的固件烧录和版本归档来说基本就是“垃圾”。它们不仅占用宝贵的硬盘空间一个复杂工程轻松就能产生上百兆的中间文件还会在你打包工程分享给同事、上传到版本库或者备份时造成不必要的流量和时间浪费。更头疼的是这些文件有时会导致一些玄学问题比如明明代码没改重新编译却报错清理一下工程目录反而就好了。手动删除面对几十上百个分散在不同子文件夹里的文件这显然是个费力不讨好的活儿。而Keil自带的“Project - Clean”功能清理得并不彻底很多文件类型它并不会碰。这时候一个简单高效的自动化清理工具就显得尤为重要。今天要分享的就是一个利用Windows批处理.bat脚本打造的“Keil工程深度清洁工”。它不是什么高深技术但绝对是提升日常开发效率、保持工程目录整洁的利器。无论你是刚接触MCU的新手还是经验丰富的嵌入式老鸟这个脚本都能让你从繁琐的文件清理工作中解放出来。2. 脚本核心原理与逐行解析这个批处理脚本的本质是使用Windows命令行下的del命令配合通配符和目录遍历参数对指定类型的文件进行批量删除。我们先把完整的脚本内容贴出来然后逐一拆解每一行的作用和背后的考量。del *.bak /s del *.ddk /s del *.edk /s del *.lst /s del *.lnp /s del *.mpf /s del *.mpj /s del *.obj /s del *.omf /s ::del *.opt /s ::不允许删除JLINK的设置 del *.plg /s del *.rpt /s del *.tmp /s del *.__i /s del *.crf /s del *.o /s del *.d /s del *.axf /s del *.tra /s del *.dep /s del JLinkLog.txt /s del *.iex /s del *.htm /s del *.sct /s del *.map /s exit2.1 命令基石del命令详解del是Delete的缩写是Windows命令行中用于删除文件的命令。其基本语法是del [选项] 文件名。在这个脚本中我们主要用到了两个关键部分文件名参数如*.bak这里的*是通配符代表任意字符。*.bak就表示所有扩展名为.bak的文件。这让我们能够用一行命令定位到同一类文件。关键选项/s这是整个脚本的灵魂。/s参数表示从当前目录及所有子目录Subdirectories中删除指定的文件。没有这个参数del命令只会删除当前目录下的匹配文件对于Keil工程常见的User、Output、Listings等子目录结构就无能为力了。加上/s脚本就能深入工程文件夹的每一个角落进行清理。2.2 文件类型黑名单我们删除了什么脚本中每一行都对应一种或一类Keil MDK编译生成的文件。了解它们是什么有助于你在自定义脚本时做出明智决策。*.bak: 项目文件.uvprojx或旧的.uvproj的备份文件。Keil在保存工程时自动生成。*.ddk,*.edk: 可能与早期版本的Keil或某些插件相关通常为临时或配置数据文件。*.lst: 列表文件Listing File。这是编译器生成的汇编列表文件包含了C代码与对应汇编指令的映射常用于深度调试和性能分析。对于日常开发和非调试版本可以安全删除。*.lnp: 链接器输入文件Linker Input File由Keil生成用于传递给链接器的参数。*.mpf,*.mpj: 可能的多项目文件或临时文件。*.obj: 目标文件Object File。这是编译器将每个.c源文件编译后生成的二进制中间文件包含了机器代码和符号信息。链接器Linker会将这些.obj文件链接成最终的可执行文件。这是占用空间的大户之一必须清理。*.omf: 另一种目标模块格式文件。*.plg: 编译日志文件Project Log。记录了上一次编译的过程和信息包括警告和错误。查看它可以复盘编译问题但一般无需保留。*.rpt: 可能的各种报告文件。*.tmp: 临时文件无保留价值。*.__i: 编译器预处理阶段的临时文件。*.crf: 交叉引用文件Cross-Reference用于浏览代码中的符号定义和引用在IDE内浏览代码时有用但非必需。*.o: 等同于*.obj是GCC/ARM GCC工具链生成的目标文件扩展名。如果你的工程使用了ARM Compiler 6AC6或兼容GCC的配置就会生成.o文件。这也是空间占用大户。*.d: 依赖文件Dependency File。由编译器生成记录了源文件所包含的头文件依赖关系用于实现增量编译。删除后下次编译会重新生成略微增加全编译时间但无其他影响。*.axf: ARM可执行文件ARM eXecutable Format。这是链接器生成的、包含完整调试信息的可执行文件用于调试和通过J-Link、ST-Link等工具下载到芯片。注意这是可以直接下载到芯片运行的文件通常我们保留最新编译的.axf用于调试但归档时可以删除因为它可以通过源代码重新编译生成。*.tra: 可能为跟踪文件或临时文件。*.dep: 依赖文件类似.d文件。JLinkLog.txt: J-Link调试器生成的日志文件。会记录调试会话信息文件可能变得很大。*.iex: 可能为IntelliSense相关索引文件。*.htm: Keil生成的某些HTML格式的报告。*.sct: 分散加载文件Scatter-Loading File的副本或中间文件。真正的链接脚本如*.sct是工程的重要组成部分通常手动创建并保存在项目目录不应被删除。脚本这里删除的可能是编译过程中生成的临时副本。*.map: 内存映射文件Memory Map File。这是链接器生成的重要文件详细列出了程序中每个函数、变量在内存中的地址、大小以及堆栈的使用情况。对于分析内存占用、优化代码至关重要是调试阶段的宝贵资料。建议在需要分析时保留日常清理或归档时可删除。2.3 特殊行解析与注意事项脚本中有一行被注释掉了::del *.opt /s ::不允许删除JLINK的设置::在批处理中双冒号是注释符表示该行不会被执行。*.opt: 这是Keil工程的工作区选项文件。它保存了当前用户的个性化设置比如窗口布局、调试器配置包括J-Link、ST-Link的具体设置、书签等。删除这个文件会导致你的工程恢复默认设置所有调试器配置需要重新配非常麻烦。因此原脚本作者特意将其注释掉并加了说明。这是一个非常重要的避坑点。重要提示*.uvoptx文件对于Keil MDK v5工程和*.opt文件对于旧版工程包含了用户的调试配置。绝对不要将它们纳入常规清理范围除非你确定要重置所有工程设置。3. 脚本的创建、使用与自定义实战3.1 从零开始创建你的清理脚本操作非常简单但有几个细节需要注意以确保脚本在任何电脑上都能可靠运行。新建文本文件在任意位置比如桌面右键新建一个文本文档命名为keilkill.txt名字随意。编辑脚本内容用记事本Notepad打开这个文件。我强烈建议使用更专业的文本编辑器如 Notepad、VS Code 或 Sublime Text。原因有两点一是记事本默认的编码和换行符有时会导致批处理脚本运行异常二是专业编辑器有语法高亮更方便查看。粘贴与修改将上面解析过的脚本内容或者根据你需求调整后的内容粘贴进去。关键一步修改文件扩展名关闭文本编辑器。在Windows资源管理器中找到这个keilkill.txt文件。点击“查看”菜单确保“文件扩展名”选项是打勾的这样你才能看到并修改.txt这个后缀。右键点击文件 - “重命名”将文件名从keilkill.txt改为keilkill.bat。系统会弹出警告“如果改变文件扩展名可能会导致文件不可用。确实要更改吗”点击“是”。此时文件的图标通常会变成一个齿轮或两个齿轮叠在一起的样式这表示它现在是一个可执行的批处理文件。3.2 如何正确放置与运行脚本脚本的位置决定了它清理的范围。最佳位置将keilkill.bat文件复制到你Keil工程的最顶层目录。所谓最顶层目录就是包含.uvprojx或.uvproj工程文件的那一层。运行方法方法一直接双击keilkill.bat文件。你会看到一个黑色的命令提示符CMD窗口快速闪过如果文件较多窗口会停留稍长时间显示删除的文件列表然后自动关闭。方法二在资源管理器的地址栏输入cmd并回车会在此目录打开命令行窗口。然后输入keilkill.bat并回车。这种方式的好处是如果脚本有错误比如语法错误窗口不会立即关闭你可以看到错误信息以便调试。运行效果脚本会从你放置它的目录开始递归搜索所有子文件夹删除所有匹配到的文件类型。你的源代码文件.c,.h、工程文件.uvprojx、链接脚本.sct源文件等核心资产都不会被触动。3.3 高级自定义打造你的专属清理脚本原脚本是一个很好的起点但不同的工具链、开发习惯可能需要不同的清理策略。1. 添加需要清理的新文件类型假设你的工程开始使用CMSIS-DAP调试器它可能会生成CMSIS_DAP.log文件。或者你使用了CppUTest单元测试框架会生成*.exe等测试执行文件。你只需要在脚本末尾exit命令之前添加新行即可del CMSIS_DAP.log /s del *.exe /s2. 排除不想清理的文件类型正如我们看到的*.opt例子如果你发现某个.bat脚本删除了一些你希望保留的文件你有两种选择方案A推荐像原脚本一样在该行前面加上::将其注释掉。::del *.map /s ::我经常需要分析内存所以暂时不删除map文件方案B直接删除该行命令。3. 增加安全确认与日志功能进阶直接双击删除总让人有点不放心。我们可以给脚本加点“保险丝”和“记录仪”。echo off echo echo Keil工程清理脚本 (安全模式) echo echo 此操作将删除所有编译生成的中间文件。 echo 包括*.obj, *.o, *.axf, *.map, *.lst 等。 echo. set /p choice是否继续(输入 Y 确认输入其他任意键取消): if /i not %choice%Y ( echo 操作已取消。 pause exit /b ) echo 开始清理... cleanup_log.txt echo %date% %time% cleanup_log.txt echo --------------------------- cleanup_log.txt del *.bak /s cleanup_log.txt 21 del *.obj /s cleanup_log.txt 21 del *.o /s cleanup_log.txt 21 del *.axf /s cleanup_log.txt 21 :: ... 其他del命令 echo --------------------------- cleanup_log.txt echo 清理完成 cleanup_log.txt echo 详细日志已保存到 cleanup_log.txt pauseecho off关闭命令本身的回显让输出更整洁。set /p choice提示用户输入实现确认环节。 cleanup_log.txt和 cleanup_log.txt将命令的输出重定向到日志文件。是覆盖是追加。21表示将错误信息也重定向到相同位置。pause执行完后暂停让你有时间查看信息。4. 针对不同编译配置的差异化清理有时你的工程可能有Debug和Release等不同配置输出目录不同例如./Debug/,./Release/。你可以创建多个批处理文件或者让一个脚本更智能echo off echo 请选择要清理的配置 echo 1. 清理 Debug 输出目录 echo 2. 清理 Release 输出目录 echo 3. 清理所有中间文件全工程 set /p config请输入数字 (1, 2, 3): if %config%1 ( if exist Debug ( del Debug\*.obj /s del Debug\*.axf /s echo 已清理 Debug 目录。 ) else ( echo Debug 目录不存在。 ) ) else if %config%2 ( if exist Release ( del Release\*.obj /s del Release\*.axf /s echo 已清理 Release 目录。 ) else ( echo Release 目录不存在。 ) ) else if %config%3 ( call :CleanAll ) else ( echo 输入无效。 ) pause exit /b :CleanAll echo 开始全工程清理... del *.bak /s del *.obj /s del *.o /s :: ... 其他全清理命令 echo 全工程清理完成。 goto :eof4. 常见问题、避坑指南与进阶技巧4.1 为什么脚本运行后窗口一闪而过这是正常现象说明脚本执行完毕。如果想知道它具体做了什么或者怀疑有错误有几种方法在命令行中运行如前所述在脚本所在目录打开CMD然后输入脚本名运行。在脚本末尾添加pause命令这样脚本执行完后会暂停显示“请按任意键继续. . .”。使用日志功能如上节进阶脚本所示将输出重定向到文件。4.2 误删了重要文件怎么办这是最令人担心的问题。预防永远胜于治疗。首次使用前先备份在一个不重要的测试工程上先运行脚本确认无误后再用于主要工程。使用版本控制系统这是最根本、最推荐的解决方案。务必使用 Git、SVN 等版本控制系统管理你的源代码。将.gitignore文件配置好忽略所有编译生成文件如*.obj,*.axf,*.map等。这样即使本地文件被误删你也可以随时从仓库中恢复源代码。版本库只保存源代码、工程文件和必要的脚本体积小传输快。自定义“安全脚本”将绝对不允许删除的文件类型如*.uvoptx,*.sct源文件你自己的重要文档从脚本中移除或注释掉。回收站不批处理的del命令是直接永久删除不经过回收站。对于特别重要的工程可以考虑先使用文件压缩软件如7-Zip将整个工程目录打包备份再运行清理脚本。4.3 脚本在某些文件夹下报“拒绝访问”错误这可能是因为文件正在被占用Keil IDE 可能还打开着该工程或者某个文件被其他进程锁定。关闭Keil和相关程序再运行脚本。权限不足如果你把工程放在系统保护目录如C:\Program Files下可能需要以管理员身份运行CMD和脚本。但更好的做法是将工程放在用户目录如D:\Projects下。4.4 如何集成到Keil IDE中实现一键清理让清理变得更方便你可以将批处理脚本集成到Keil的菜单里。打开Keil进入Project - Manage - Project Items。切换到Folders/Extensions选项卡。在Custom Files框里点击...按钮添加你的keilkill.bat文件。确定后你会在工程窗口的Project栏下看到这个.bat文件。右键点击它选择Options for File在File Type下拉框中可以选择“Other”这样Keil就不会尝试以文本形式打开它。以后需要清理时直接在Keil工程里双击这个keilkill.bat文件即可运行。4.5 除了Keil这个思路还能用在哪儿批处理脚本的清洁思路是通用的。IAR Embedded Workbench清理*.dep,*.pbi,*.pbd,*.pbt,*.log以及Debug\Exe,Release\Exe下的输出文件。VS Code PlatformIO清理.pio\build目录下的所有内容。Eclipse CDT清理Debug和Release构建目录。任何会产生中间文件的编译环境如LaTeX编译产生的.aux,.log,.out文件Python运行产生的__pycache__目录和.pyc文件。你只需要研究一下对应工具链生成的文件类型然后照猫画虎修改文件扩展名列表即可。例如一个通用的C/C项目清理脚本可能包含del *.obj /s del *.o /s del *.ilk /s del *.pdb /s del *.pch /s del *.sbr /s del *.bsc /s del *.ncb /s del *.suo /s del /q /s Debug Release 2nul最后一行尝试删除名为Debug和Release的整个文件夹/q安静模式2nul隐藏错误信息这适用于很多IDE的默认输出目录结构。4.6 从批处理到更强大的工具批处理简单直接但功能有限。如果你需要更复杂、跨平台Windows/macOS/Linux的清理方案可以考虑使用 Python 脚本利用os和shutil库可以更精细地控制文件删除逻辑支持更复杂的模式匹配和条件判断。使用 CMake 或 Makefile在构建系统中集成清理目标如make clean或cmake --build . --target clean这是最规范的方式。使用专门的清理工具如ccache或sccache来管理编译缓存而不是简单删除。然而对于大多数嵌入式开发者尤其是Windows平台下的Keil用户一个精心编写、放在工程根目录的.bat文件依然是那个最顺手、最快速的“工程清洁工”。它不炫技但切实地解决了一个高频痛点把时间还给真正的创造和调试工作。