FORFILES(ファイルの一括処理)
「30 日以上前のログファイルだけを削除したい」「特定の拡張子のファイルすべてに同じ処理を行いたい」といった場面があります。
FORFILES コマンドは、条件に合うファイルを選び出し、1 つずつに対して、指定したコマンドを実行するコマンドです。ファイルの更新日時で絞り込めるため、古いファイルの整理に向いています。
基本的な使い方
FORFILES [/P ディレクトリ] [/M 検索マスク] [/S] [/C "コマンド"] [/D [+|-]日付または日数]
すべてのオプションは省略できます。省略した場合は、カレントディレクトリにあるすべてのファイルとフォルダーの名前を表示します。
forfiles
名前がダブルクォーテーションで囲まれて表示される点に注意してください。
主要オプション
| オプション | 説明 |
|---|---|
/P ディレクトリ | 検索を開始するディレクトリ(省略時はカレントディレクトリ) |
/M 検索マスク | 対象とするファイル名。ワイルドカードが使える(省略時はすべてのファイル) |
/S | サブディレクトリも再帰的に検索する |
/C "コマンド" | 各ファイルに対して実行するコマンド(省略時は cmd /c echo @file) |
/D 日付または日数 | 最終更新日で絞り込む。次の節で詳しく解説 |
拡張子を指定してファイルを処理する
/M で対象を絞り、/C で実行するコマンドを指定します。
forfiles /M *.log /C "cmd /c echo @file"
/C のコマンドの中では、処理中のファイルの情報を @変数 で参照できます。
| 変数 | 内容 |
|---|---|
@file | ファイル名(拡張子を含む) |
@fname | 拡張子を除いたファイル名 |
@ext | 拡張子(ドットは含まない) |
@path | ファイルのフルパス |
@relpath | /P で指定したディレクトリからの相対パス |
@isdir | ディレクトリなら TRUE、ファイルなら FALSE |
@fsize | ファイルサイズ(バイト) |
@fdate | 最終更新日 |
@ftime | 最終更新時刻 |
forfiles /P C:\Logs /M *.log /C "cmd /c echo @path @fsize バイト"

中小企業経営者のためのRPA入門 RPA導入を成功させる方法

60分でわかる! AIエージェント 超 入門

コマンドラインの黒い画面が怖いんです。

知識・才能ゼロでもらく~に月10万円稼ぐ! よくわかるAI副業超入門
@file や @path は、値の前後にダブルクォーテーションが付いた状態で展開されます。そのため、del @path のようにそのまま渡せば、スペースを含むパスでも正しく動作します。"@path" のように自分で囲む必要はありません。
内部コマンドは cmd /c 経由で実行する
FORFILES は、/C で指定されたコマンドを別プロセスとして起動します。echo や del のようにコマンドプロンプトに組み込まれた内部コマンドは単独の実行ファイルではないため、cmd /c を付けて呼び出す必要があります。
forfiles /M *.txt /C "echo @file"
forfiles /M *.txt /C "cmd /c echo @file"
/C を省略したときの既定値が cmd /c echo @file であるのも、同じ理由です。
.exe ファイルのような外部コマンドであれば、cmd /c なしでも実行できます。たとえば forfiles /M *.txt /C "notepad @file" です。
更新日時で絞り込む(/D)
/D オプションは、ファイルの最終更新日で対象を絞り込みます。日数または日付で指定できます。
| 指定方法 | 意味 |
|---|---|
/D -30 | 最終更新日が 30 日前以前のファイル |
/D -2025/01/01 | 最終更新日が 2025 年 1 月 1 日以前のファイル |
/D 2025/01/01 | 最終更新日が 2025 年 1 月 1 日以降のファイル |
符号を省略した場合は + として扱われます。日付の形式は OS の地域設定に依存します(日本語環境では yyyy/MM/dd、Microsoft の資料では MM/DD/YYYY)。@fdate の出力形式も同様に地域設定に従います。日数での指定であれば、形式の違いを気にする必要はありません。
forfiles /P C:\Logs /M *.log /D -7 /C "cmd /c echo @file @fdate"
/D -30 は「30 日前の日付と同じか、それより古い」ファイルを対象にします。ちょうど 30 日前に更新されたファイルも含まれる点に注意してください。
古いファイルを安全に削除する
ログの定期削除は、FORFILES の代表的な使い道です。ただし、削除は元に戻せないため、必ず次の 2 段階で進めてください。
手順 1:削除せず、対象を表示して確認する
forfiles /P C:\Logs /M *.log /S /D -30 /C "cmd /c if @isdir==FALSE echo @path"
手順 2:表示された対象に問題がなければ、echo を del に置き換える
/M *.log はフォルダーにも一致するため、if @isdir==FALSE でファイルだけに限定しています。プレビューと削除で同じ条件を使ってください。
forfiles /P C:\Logs /M *.log /S /D -30 /C "cmd /c if @isdir==FALSE del @path"
del で削除したファイルはごみ箱に入りません。/P のパスを誤ると、意図しないファイルを削除してしまいます。実行前に、手順 1 で必ず対象を確認してください。
サブフォルダーを含めて処理する(/S)
/S を付けると、/P で指定したディレクトリ以下のすべてのサブフォルダーも対象になります。
forfiles /P C:\Docs /S /M *.txt /C "cmd /c echo @relpath"
@relpath は ".\sub\note.txt" のように、/P で指定したディレクトリからの相対パスを返します。
フォルダーだけを対象にする
@isdir を使うと、ファイルとフォルダーを区別できます。
forfiles /P C:\Docs /C "cmd /c if @isdir==TRUE echo @file"
特殊文字を指定する
/C の中でダブルクォーテーションなどを使いたい場合は、0xHH の形式で 16 進数のコードを指定できます。
forfiles /M *.txt /C "cmd /c echo 0x22@fname0x22"
0x22 はダブルクォーテーション(")を表します。
バッチファイルで使うときのポイント
対象が見つからない場合
条件に合うファイルが 1 つもなかった場合、FORFILES はエラーメッセージを表示し、ERRORLEVEL に 0 以外の値を設定します。バッチファイルで「対象なし」を判定したいときに利用できます。ただし、パスの誤りなど他のエラーでも 1 になるため、厳密な判定には向きません。
@echo off
forfiles /P C:\Logs /M *.log /D -30 >nul 2>&1
if errorlevel 1 (
echo 削除対象のログはありません。
) else (
echo 30 日以上前のログが見つかりました。
)
バッチファイル内の % について
FORFILES の @変数は @ で始まるため、バッチファイル内でも % を重ねる必要はありません。一方、%LOG_DIR% のような変数をパスに使う場合は、スペース対策としてダブルクォーテーションで囲んでください。
@echo off
set LOG_DIR=C:\My Logs
set DAYS=30
forfiles /P "%LOG_DIR%" /M *.log /S /D -%DAYS% /C "cmd /c echo @path"
ファイル名の一覧に対して処理を繰り返すだけなら FOR コマンドでも実現できます。ただし FOR では更新日時を簡単には比較できないため、日付条件が必要なときは FORFILES が便利です。
まとめ
| 操作 | コマンド |
|---|---|
| ファイル名を一覧表示 | forfiles /M *.log |
| 内部コマンドを実行する | forfiles /C "cmd /c echo @file" |
| サブフォルダーも対象にする | forfiles /S |
| N 日以上前のファイルを抽出 | forfiles /D -N |
| 開始ディレクトリを指定 | forfiles /P ディレクトリ |
| フルパスで処理する | @path |