forfiles выбирает файлы по маске и дате и выполняет для каждого заданную команду. Самое частое применение - автоматическая очистка: удалить логи, резервные копии или временные файлы старше определённого числа дней. Команда встроена в Windows и Windows Server, ничего устанавливать не нужно.
Синтаксис
forfiles [/P путь] [/M маска] [/S] [/D дата] [/C "команда"]
- /P - папка, с которой начинать. По умолчанию текущая.
- /M - маска имени файла, например
*.log. По умолчанию*(все файлы). - /S - обрабатывать и вложенные папки.
- /D - отбор по дате изменения:
/D -30- изменённые 30 и более дней назад;/D +30- формально «с датой изменения не раньше, чем через 30 дней от сегодня», то есть почти ничего не находит. Чтобы выбрать свежие файлы, указывайте дату;/D -датаили/D +дата- до или после конкретной даты. Формат даты зависит от региональных настроек, в русской Windows этоДД.ММ.ГГГГ.
- /C - команда для каждого файла. По умолчанию
"cmd /c echo @file", то есть просто вывод имени.
Переменные внутри команды
| Переменная | Значение |
|---|---|
@file |
имя файла с расширением, в кавычках |
@fname |
имя без расширения |
@ext |
расширение |
@path |
полный путь к файлу, в кавычках |
@relpath |
путь относительно папки /P |
@isdir |
TRUE для папки, FALSE для файла |
@fsize |
размер в байтах |
@fdate, @ftime |
дата и время изменения |
Встроенные команды cmd (del, echo, rmdir, move) нужно вызывать через cmd /c, иначе forfiles их не найдёт.
Примеры
Посмотреть, что будет удалено
Перед удалением всегда проверяйте выборку:
forfiles /P "D:\Logs" /S /M *.log /D -30 /C "cmd /c echo @path @fdate"
Удалить файлы старше 30 дней
forfiles /P "D:\Logs" /S /M *.log /D -30 /C "cmd /c del /q @path"
Удалить только файлы, не трогая папки
Маска * захватывает и папки. Чтобы удалить только файлы:
forfiles /P "D:\Temp" /S /D -7 /C "cmd /c if @isdir==FALSE del /q @path"
Удалить старые папки целиком
Например, папки ежедневных резервных копий старше 14 дней:
forfiles /P "E:\Backup" /D -14 /C "cmd /c if @isdir==TRUE rmdir /s /q @path"
Без /S команда смотрит только на папки первого уровня. Дата изменения папки - это время последнего изменения её списка файлов, а не самого нового файла внутри.
Перенести старые файлы в архивную папку
forfiles /P "D:\Reports" /M *.xlsx /D -90 /C "cmd /c move @path D:\Reports\Archive\"
Найти большие файлы
forfiles /P "D:\Share" /S /C "cmd /c if @fsize GEQ 1073741824 echo @path @fsize"
Сравнение с числами больше 2 ГБ в cmd работает ненадёжно - для больших порогов используйте PowerShell.
Особенности и ошибки
ERROR: No files found with the specified search criteria. Если подходящих файлов нет, forfiles выводит это сообщение и возвращает код ошибки 1. В пакетном файле это может выглядеть как сбой. Сообщение скрывается перенаправлением:
forfiles /P "D:\Logs" /M *.log /D -30 /C "cmd /c del /q @path" 2>nul
Сетевые папки. Путь вида \\server\share в параметре /P не поддерживается. Подключите папку на время работы через pushd - команда сама назначит временную букву диска:
pushd \\fs01\logs
forfiles /S /M *.log /D -30 /C "cmd /c del /q @path"
popd
Пробелы в путях. @path и @file уже в кавычках, дополнительные кавычки вокруг них не нужны. Сам путь в /P берите в кавычки.
Кавычки внутри команды. Если внутри /C нужны свои кавычки, используйте шестнадцатеричный код 0x22: /C "cmd /c echo 0x22@fname0x22".
Запуск по расписанию

Сохраните команду в пакетный файл, например C:\Scripts\cleanup.cmd, и создайте задание планировщика:
schtasks /Create /TN "Очистка логов" /TR "C:\Scripts\cleanup.cmd" /SC DAILY /ST 03:00 /RU SYSTEM
Задание будет запускаться каждую ночь от имени системы. Убедитесь, что у учётной записи задания есть права на удаление в нужной папке. Для сетевых папок «Система» не подойдёт: используйте учётную запись с доступом к общей папке.
То же на PowerShell
В PowerShell фильтр по дате пишется прямо в конвейере, и тот же подход работает с сетевыми путями без pushd:
Get-ChildItem "D:\Logs" -Recurse -File -Filter *.log |
Where-Object LastWriteTime -lt (Get-Date).AddDays(-30) |
Remove-Item -WhatIf
Ключ -WhatIf показывает, что будет удалено, не удаляя. Когда результат устраивает, уберите его. Для папок замените -File на -Directory и добавьте -Recurse к Remove-Item.





Комментарии
Комментариев пока нет - будьте первым.