forfiles 是什么
forfiles 是 Windows 自带的选择文件并批量执行命令的工具,核心能力是按「最后修改时间」筛选:找出 N 天前没动过的文件,对每个文件执行一次指定命令。它是纯 CMD 环境下做旧日志清理、过期文件归档的标准方案,配合计划任务就能实现无人值守的定期清理。代价是它会对每个命中文件单独启动一次进程,海量小文件场景性能明显不如 PowerShell 管道。
基本信息
| 适用平台 | Windows 7/10/11 与 Windows Server(CMD、批处理、计划任务) |
|---|---|
| 语法 | forfiles /P 目录 [/S] [/M 模式] /D ±天数 /C "命令" |
| 参数 | /P 起始目录、/S 递归子目录、/M 文件掩码、/D 时间条件、/C 对每个文件执行的命令 |
| 内置变量 | @file 文件名、@fname 不含扩展名、@ext 扩展名、@path 完整路径、@relpath 相对路径、@isdir 是否目录、@fsize 大小、@fdate 日期 |
| 时间语义 | /D -30 表示修改时间早于或等于 30 天前;/D +30 表示 30 天以后 |
| 权限要求 | 能否删除取决于对目标目录的写权限;跨用户目录需提权 |
典型使用场景
- 日志清理:删除或归档 30 天前的 *.log,控制磁盘占用
- 过期文件归档:把半年未改动的备份文件挑出来转移到归档盘
- 发布残留清理:清理构建目录里超过 7 天的临时包
- 巡检告警:找出指定目录中迟迟没有更新的文件,说明任务可能已停摆
- 混合筛选:按掩码缩小范围,只处理某一类文件
常用示例
常用示例
REM 先预览将命中哪些文件,确认无误再改动作
forfiles /P D:\logs /S /M *.log /D -30 /C "cmd /c echo @path"
REM 命中文件的信息(大小与修改日期)
forfiles /P D:\logs /S /M *.log /D -30 /C "cmd /c echo @fdate @fsize @file"
REM 确认后改为删除,路径含空格时用 0x22 充当引号
forfiles /P D:\logs /S /M *.log /D -30 /C "cmd /c del /q 0x22@path0x22"
REM 只处理文件、跳过子目录本身
forfiles /P D:\data /D -180 /C "cmd /c if @isdir==FALSE echo @relpath"
REM 放进计划任务:每天 02:00 清理
schtasks /Create /TN CleanLogs /TR "forfiles /P D:\logs /S /M *.log /D -30 /C \"cmd /c del /q 0x22@path0x22\"" /SC DAILY /ST 02:00参数与变量读法
| 项目 | 含义 | 注意 |
|---|---|---|
| /D -30 | 修改时间早于或等于 30 天前 | 含边界当天,勿写成 -0 |
| /M *.log | 文件名掩码,支持通配符 | 不加 /S 只在当前层查找 |
| @path | 完整路径(含文件名) | 含空格时必须加引号或用 0x22 |
| @relpath | 相对 /P 的路径 | 自带 .\ 前缀,拼接时注意 |
| @isdir | TRUE 或 FALSE | 不加判断时目录会被一起处理 |
默认 /C 是 cmd /c echo @file,所以省略 /C 时只是把命中的文件名打印出来——这是最安全的预览方式,先看清单再决定动作。
路径含空格时,把 @path 直接写进命令会被拆成多段,del 可能删到错误目标。forfiles 提供 0x22 代表双引号:用 0x22@path0x22 包住变量最稳妥。
大批量场景的替代做法
大批量场景的替代做法
Get-ChildItem D:\logs -Recurse -Filter *.log | Where-Object LastWriteTime -lt (Get-Date).AddDays(-30) | Remove-Item -WhatIf # 先 WhatIf 预演
Get-ChildItem D:\logs -Recurse -Filter *.log | Where-Object LastWriteTime -lt (Get-Date).AddDays(-30) | Remove-Item # 确认后执行forfiles 不会二次确认,命中即执行。删除类操作必须先跑一遍 echo 预览并把清单留档;建议先在少量文件的小目录上验证命令拼接是否与实际路径匹配。