Windows批处理实战:C盘清理、提权、任务计划与性能调优

发布时间:2026/9/18 8:18:09
Windows批处理实战:C盘清理、提权、任务计划与性能调优 简介面向Windows命令行初学者及需要编写自动化脚本的运维人员这份PDF系统梳理批处理文件的定义与常用命令帮助解决日常批量操作、任务简化与流程控制问题。资源包仅含1个PDF文件约176KB篇幅紧凑便于随时查阅。内容覆盖批处理内部命令如REM注释、ECHO回显、GOTO跳转、CALL调用、PAUSE暂停并给出可直接运行的示例流程控制部分讲解IF条件判断的三种语法包括ERRORLEVEL返回值比较、字符串比较与文件存在检测循环部分则围绕FOR命令展开涉及/L增量序列、/D目录匹配、/F文件读取以及delims、tokens、usebackq等参数用法。文档以实例驱动读者可据此理解命令执行逻辑掌握批处理脚本的编写思路提升Windows环境下的操作效率与自动化程度。对于希望减少重复手工操作的读者可借助其中的命令组合与循环判断思路逐步搭建符合自身需求的批处理流程。目前已有1518人学习下载适合边查边练、快速上手。1. 从 C 盘清理命令说起批处理在 Windows 里为什么还值得写凌晨收到告警一台 Windows 业务机 C 盘只剩几百兆远程桌面卡到输命令都费劲。这时最顺手的不是装监控 agent而是打开 cmd敲几条批处理命令把 %TEMP%、C:\Windows\Temp 和浏览器缓存目录清掉再把日志落到共享盘。cmd.exe 从 Windows NT 时代保留到现在任何一台机器都不缺写好的 bat 脚本能随镜像、随任务计划一起走不依赖额外运行时。但很多人写 bat 只停留在 copy、del、echo 三个命令一遇到带空格的路径、循环里变量不更新、需要管理员权限就卡住。下面按命令语义、脚本实例、提权与开机启动、调优边界四段展开把 for、forfiles、robocopy、schtasks、net use 这些高频命令的参数和踩坑点讲清楚适合手里管着几十台 Windows 机器、想把日常维护自动化的从业者。2. 批处理命令详解cmd.exe 的解析顺序与核心命令参数批处理难写很大一部分原因不在命令多而在 cmd.exe 的解析顺序和普通交互式命令不同。同样是 for 循环里做累加交互式敲一遍能出正确结果写成 bat 却打印出旧值。先把解释器的行为弄明白后面看 forfiles、robocopy 的参数才不会被绕进去。2.1 为什么 for 循环里的 set /a 不更新cmd.exe 读取 bat 时默认按行处理。遇到(到)的块它会先把整个块读进来然后对块内每个%变量%做一次文本替换替换完才执行。所以下面这段代码不会按直觉输出 1、2、3。echo off setlocal set n0 for /l %%i in (1,1,3) do ( set /a n1 echo 循环内 n%n% ) echo 循环外 n%n%实际输出是三行循环内 n0只有循环外的n3是对的。for /l %%i in (1,1,3)里的1,1,3表示从 1 开始、步长 1、到 3 结束set /a n1是算术累加问题出在%n%在进入块之前就被替换成 0之后每次循环都复用那个字面量 0。2.2 setlocal 与延迟展开 !var! 的用法要让变量在循环执行时实时读取需要开启延迟展开并把%n%换成!n!。setlocal给变量划定作用域endlocal或脚本自然结束时回收避免污染下一个脚本。echo off setlocal enabledelayedexpansion set n0 set LOG%~dp0run_%date:~0,4%%date:~5,2%%date:~8,2%.log for /l %%i in (1,1,3) do ( set /a n1 echo 循环内 n!n! !LOG! ) echo 循环外 n%n% !LOG! endlocalenabledelayedexpansion让!var!在运行时求值而不是读块时替换。这里%~dp0表示当前 bat 所在目录末尾自带反斜杠%date:~0,4%、%date:~5,2%、%date:~8,2%是从系统日期里截取年、月、日所以日志名会带上当天日期。注意!和文件路径里的感叹号会冲突路径里可能出现!的场合建议只对需要的块开启延迟展开或者用临时文件传递变量别全局开。2.3 常用文件与进程命令参数速查批处理里真正高频的命令集中在文件复制、删除、进程查询和进程结束上。下表是我在脚本里最常翻的参数尤其要注意robocopy的返回码和del的/a。命令常用参数说明copy/y /v简单复制/y 覆盖不提示/v 校验写入xcopy/e /i /h /y/e 含空目录/i 目标视为目录/h 含隐藏文件robocopy/e /z /r:2 /w:2 /log/z 断点续传/r 重试次数/w 重试间隔/log 追加日志del/f /s /q /a/f 强制/s 递归/q 静默/a 按属性筛选rd/s /q删除目录树/q 不确认通常和 if exist 连用tasklist/fi /fo csv/fi 过滤条件/fo csv 便于导入表格taskkill/im /f /t/im 按进程名/f 强制/t 结束子进程robocopy的返回码和普通命令不一样0 到 7 都算成功或可接受8 及以上才是失败。判断时不能写if %errorlevel% neq 0而要写if %errorlevel% geq 8否则一次正常的“有文件被复制”返回码 1 就会被误判成错误。2.4 if exist 与 for /f 解析文本的写法if exist判断路径是否存在适合在删除或注册任务前做守卫。for /f用来逐行读文本处理 CSV、日志或命令输出。echo off setlocal enabledelayedexpansion if not exist C:\Scripts\hosts.csv ( echo 缺少输入文件退出 exit /b 1 ) for /f tokens1,2 delims, %%a in (C:\Scripts\hosts.csv) do ( echo 主机%%a 角色%%b if %%bdb ( echo 发现数据库角色跳过清理 ) )tokens1,2 delims,表示按逗号切分取第 1、2 列skipn可跳过前 n 行表头eol#可把#开头行当注释。%%a、%%b是循环变量在 bat 里必须写双百分号在命令行里直接写单百分号。if %%bdb做字符串比较两边加引号可以避免空值导致的语法错误。3. 脚本实例C 盘清理与文件复制的 bat 落地脚本命令参数看懂之后真正的脚本要处理的是安全边界哪些目录允许删、删多久以前的文件、删完怎么留证据。下面用一个 C 盘清理脚本串起 forfiles、robocopy 和错误码校验每一步都可以单独拿出来跑。3.1 先做安全校验哪些目录可以进清理列表清理脚本最怕手滑删到系统关键目录。我一般只放用户临时目录、系统临时目录和明确的日志暂存目录不放C:\Windows\System32、C:\Program Files这类路径。脚本开头先把待清理目录写进变量便于以后加减。echo off setlocal enabledelayedexpansion set LOG%~dp0clean_%date:~0,4%%date:~5,2%%date:~8,2%.log set TARGETS%TEMP% C:\Windows\Temp C:\Users\Public\Documents\Temp echo [%date% %time%] 开始清理 %LOG% for %%d in (%TARGETS%) do ( if exist %%d ( echo 清理目录 %%d %LOG% forfiles /p %%d /s /m *.* /d -7 /c cmd /c del /f /q path %LOG% 21 ) else ( echo 跳过不存在的目录 %%d %LOG% ) ) echo [%date% %time%] 清理结束最近一次 errorlevel%errorlevel% %LOG% endlocalfor %%d in (%TARGETS%) do是逐个遍历目录if exist %%d做存在性判断避免对不存在的路径调用 forfilesforfiles的/p指定起始目录/s递归子目录/m *.*匹配所有文件/d -7表示修改时间早于 7 天前的文件/c后面跟对每个匹配项执行的命令path会被替换成带引号的完整路径。 %LOG% 21把标准输出和标准错误都追加进日志排查时能看到哪些文件删除失败。3.2 forfiles 按时间删除的参数怎么设/d的取值是最容易设错的地方。/d -7是 7 天以前/d 7是 7 天以后/d 2024/01/01是指定日期。如果只写/d -0会匹配当天之前的所有文件范围过大不建议在生产脚本里这么写。forfiles默认不处理只读、隐藏、系统文件遇到这些属性会返回错误。要在日志里分辨是“文件被占用”还是“权限不足”可以把/c里的命令改成cmd /c del /f /q /a path/a让 del 也处理隐藏和系统属性。但这一步要谨慎系统目录里的隐藏文件不要随手删。另一个实际问题是%TEMP%在管理员提权前后可能指向不同用户的临时目录。如果脚本以 SYSTEM 身份通过任务计划运行%TEMP%会变成C:\Windows\Temp附近而不是当前登录用户的临时目录。要在脚本里显式写C:\Users\*用户*\AppData\Local\Temp或者用for /d %%u in (C:\Users\*) do遍历用户目录再拼出各自的 Temp。3.3 复制当前目录下的文件到目标目录并写日志清理和备份经常成对出现。批处理复制当前目录下的文件关键是处理当前目录路径和日志追加。%~dp0表示 bat 所在目录%CD%表示当前工作目录两者不一样。用户双击 bat 时工作目录可能是C:\Windows\System32所以脚本内部引用文件要用%~dp0。echo off setlocal set SRC%~dp0 set DEST\\backup-server\logs\%COMPUTERNAME% set LOG%~dp0copy_%COMPUTERNAME%.log if not exist %DEST% mkdir %DEST% robocopy %SRC% %DEST% *.log *.txt /e /z /r:2 /w:2 /np /log:%LOG% if %errorlevel% geq 8 ( echo robocopy 失败errorlevel%errorlevel% %LOG% exit /b 1 ) echo robocopy 完成errorlevel%errorlevel% %LOG%set SRC%~dp0把源目录固定为脚本所在目录%COMPUTERNAME%按机器名分目录避免多台机器日志混在一起mkdir %DEST%在共享目录不存在时创建如果权限不够会报错日志里能看到robocopy后只复制*.log和*.txt/e含子目录/z支持断点续传/r:2每文件重试 2 次/w:2每次重试等 2 秒/np不显示进度百分比/log追加日志。if %errorlevel% geq 8是 robocopy 专用判断0 到 7 都不视为失败。3.4 用日志关键字做结果校验脚本跑完不能只看“窗口关了就算成功”。我通常让脚本在结束时输出固定关键字再用 findstr 做检查。例如清理脚本结束时写清理结束备份脚本结束时写robocopy 完成然后另写一条校验命令。echo off findstr /c:清理结束 %~dp0clean_%date:~0,4%%date:~5,2%%date:~8,2%.log nul if %errorlevel% neq 0 ( echo 未找到结束标记脚本可能提前中断 exit /b 2 ) findstr /c:errorlevel0 /c:errorlevel1 %~dp0copy_%COMPUTERNAME%.log nul if %errorlevel% neq 0 ( echo 复制日志中存在非成功返回码 )findstr /c:指定要查找的字面字符串nul屏蔽输出只靠 errorlevel 判断。这里findstr找到返回 0没找到返回 1。注意findstr默认按行匹配关键字要包含完整的一段避免只写“结束”匹配到别的行。4. 批处理加管理员权限与开机启动项配置很多维护脚本要删系统临时目录、改服务启动类型、写注册表这些操作在普通权限下会失败但窗口可能只闪一下就关了。让 bat 自己判断权限并提权是脚本能不能上任务计划的前提。4.1 自提权脚本的常见写法与两个坑最常见的判断是net session这个命令需要管理员权限才能成功执行普通用户会返回错误码。echo off net session nul 21 if %errorlevel% neq 0 ( echo 需要管理员权限正在尝试提权... powershell -NoProfile -Command Start-Process %~f0 -Verb RunAs exit /b ) echo 已获得管理员权限继续执行net session nul 21把正常输出和错误输出都丢掉只看%errorlevel%。不为 0 就调用 PowerShell 的Start-Process -Verb RunAs重新启动自身%~f0是当前 bat 的完整路径外面用单引号包住路径里有空格也不会被拆开。第一个坑是 UAC 弹窗被用户取消后提权进程不会启动原进程已经exit /b脚本看起来什么都没做第二个坑是提权后的进程工作目录变成C:\Windows\System32脚本内部必须用%~dp0或绝对路径不能依赖%CD%。还有一种用mshta调 VBScript 提权的写法代码更短但容易被杀软拦截我不建议在受管机器上使用。如果 PowerShell 受执行策略限制-Command形式一般不触发脚本文件执行策略直接调Start-Process是可行的。4.2 用 schtasks 注册开机启动脚本手动把 bat 拖进启动文件夹只对当前用户登录生效而且用户可能关掉。更稳的是用任务计划注册开机启动并指定 SYSTEM 身份和高权限运行。schtasks /create /tn CleanTempOnStart /tr C:\Scripts\clean_temp.bat /sc onstart /ru SYSTEM /rl HIGHEST /delay 0005:00 /f schtasks /query /tn CleanTempOnStart /v /fo LIST/tn是任务名/tr是要运行的程序路径/sc onstart表示系统启动时触发/ru SYSTEM以 SYSTEM 账户运行/rl HIGHEST请求最高权限/delay 0005:00延迟 5 分钟避开开机初期磁盘和网络繁忙时段/f表示同名任务直接覆盖。查询时用/query /tn 任务名 /v /fo LIST可以看到上次运行结果和返回码。如果把 bat 放在网络共享上SYSTEM 账户需要访问权限最好先复制到本地目录再注册。4.3 批处理连接共享打印机办公网里经常需要批量给机器挂共享打印机。批处理可以用rundll32调 printui.dll 完成连接也可以用net use映射端口再安装驱动。前者更直接。echo off set PRINTER\\print-server\HP-M1136 rundll32 printui.dll,PrintUIEntry /in /n %PRINTER% if %errorlevel% neq 0 ( echo 打印机连接失败检查共享名、凭据和网络连通性 exit /b 1 ) echo 打印机连接成功rundll32 printui.dll,PrintUIEntry是 Windows 自带的打印机配置入口/in表示安装网络打印机/n后面跟打印机共享路径。如果报错先用ping print-server确认名称解析再用telnet print-server 445测试端口不过 Windows 默认没装 Telnet 客户端也可以在 PowerShell 里用Test-NetConnection print-server -Port 445。权限方面连接共享打印机需要域用户或本地管理员凭据SYSTEM 账户在跨域场景下可能失败。4.4 排错表编码、路径空格与 errorlevel现象常见原因处理方式中文输出乱码bat 保存编码与代码页不一致用 ANSI/GBK 保存或脚本开头chcp 65001并确认字体支持路径带空格执行失败变量展开后没加引号所有路径变量在使用时加双引号如%DEST%errorlevel 判断总是不对把 robocopy 当普通命令判断robocopy 用geq 8普通命令用neq 0脚本双击一闪而过缺少暂停或日志末尾加pause生产脚本写日志并用退出码任务计划里运行失败工作目录或账户权限不对用绝对路径检查/ru账户对源目录和共享目录的权限chcp 65001切到 UTF-8 代码页后部分旧版控制台字体仍显示方块最稳的是把 bat 本身保存为 ANSI/GBK。日志文件建议用追加不要用覆盖否则第二次运行会丢掉第一次的排错信息。判断 errorlevel 时注意if errorlevel 1表示“大于等于 1”不是“等于 1”要精确比较就用if %errorlevel% equ 1。5. 进阶用批处理做系统调优与游戏性能优化的边界网上能搜到用 bat 优化 Windows 游戏性能的脚本常见动作是切高性能电源计划、停掉后台服务、刷新 DNS、清理临时文件。这些命令本身没错但批量禁用服务的脚本往往把打印、更新、域认证相关服务一起关掉问题会在几天后集中爆发。下面按可回滚的方式给命令并说明验证手段。5.1 电源模式切换与后台服务白名单电源计划有固定 GUID高性能计划的 GUID 是8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c卓越性能计划需要先通过powercfg -duplicatescheme e9a42b02-d5df-448d-aa00-03f14749eb61创建。echo off powercfg /setactive 8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c powercfg /getactivescheme sc query SysMain sc config SysMain start disabledpowercfg /setactive按 GUID 切换当前电源计划/getactivescheme回显确认。sc query查看服务状态sc config改启动类型注意start后面必须有空格写成startdisabled会报参数错误。可考虑禁用的服务要限定在 SysMain、Windows Search 这类对游戏帧率影响小、禁用后不影响系统更新的项上RpcSs、DcomLaunch、Themes 这些不要动。改完用sc query SysMain确认STATE变成STOPPED或启动类型生效。5.2 网络延迟相关命令与注册表查询网络部分能安全用 bat 做的通常是刷新 DNS 缓存和查看 TCP 全局参数不要写修改代理、修改路由表的脚本。ipconfig /flushdns netsh int tcp show global reg query HKLM\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces /s /v TcpAckFrequencyipconfig /flushdns清空本机 DNS 缓存适合切换 DNS 服务器或排查解析问题时执行。netsh int tcp show global查看接收窗口自动调整、ECN 等全局参数输出里Receive Window Auto-Tuning Level通常保持normal。reg query只是查询每个网卡接口下是否设置过TcpAckFrequency这个值会影响 TCP ACK 行为改注册表后需要重启网卡或重启系统不建议在没有回滚方案时批量改。5.3 用前后对比验证调优是否有效调优脚本最容易变成“心理作用”所以每次改完都要记录前后数据。下面几条命令可以放进同一个 bat输出到日志里做对比。echo off set LOG%~dp0perf_%date:~0,4%%date:~5,2%%date:~8,2%.log echo 系统时间 %date% %time% %LOG% systeminfo | findstr /C:Available Physical Memory %LOG% wmic logicaldisk where DeviceIDC: get FreeSpace,Size %LOG% powercfg /getactivescheme %LOG% sc query SysMain %LOG%systeminfo | findstr /C:Available Physical Memory取可用物理内存行wmic logicaldisk取 C 盘剩余空间和总大小powercfg /getactivescheme确认当前电源计划sc query确认目标服务状态。把这些输出追加到按日期命名的日志跑两三天后对比可用内存和磁盘剩余空间的变化再决定是否保留某项调优。清理脚本和优化脚本建议分开跑先执行清理再执行电源和服务调整最后用同一套日志模板记录出问题时能按时间点回退。本文还有配套的精品资源点击获取