【bat】ファイルを削除する方法完全ガイド|del・forfiles・rd・世代管理・安全な削除パターンまで

「古いログファイルを定期削除したい」「拡張子別に不要ファイルを一掃したい」——バッチファイルでのファイル削除は自動化の定番です。本記事では del コマンドのオプション全解説から、forfiles による日付条件付き削除、rd でのフォルダ削除、誤削除を防ぐ安全パターン、よくある落とし穴まで体系的に解説します。

この記事で解決できること

  • del コマンドの全オプション(/Q /F /S /A)の意味と使い方
  • ワイルドカードで特定の拡張子・ファイル名パターンのファイルを一括削除
  • forfiles /d -30 で「30日より古いファイル」を自動削除する方法
  • rd /s /q でフォルダごと中身ごと削除する方法
  • 削除前の存在確認・削除ログ記録による安全な運用パターン
  • 読み取り専用・隠しファイルの削除方法と落とし穴
del で削除したファイルはゴミ箱に入らない
del コマンドによる削除はゴミ箱を経由しません。削除したファイルは即座に復元できなくなります。
本番環境で実行する前には必ず 削除対象の確認 を行い、重要なファイルには事前バックアップを取っておきましょう。
スポンサーリンク
  1. del コマンドの構文と主なオプション
  2. 方法1: 単一ファイルを削除する
    1. 基本: 指定ファイルを削除
  3. 方法2: ワイルドカードで複数ファイルを一括削除
    1. 特定の拡張子をまとめて削除
    2. ファイル名パターンで絞り込んで削除
    3. サブフォルダも含めて再帰的に削除
  4. 方法3: forfiles で日付条件付き削除
    1. 30日より古いファイルを削除
    2. 特定日付より前のファイルを削除
    3. サブフォルダも含めて古いファイルを削除
  5. 方法4: for + del で柔軟なフィルタリング削除
    1. 特定のファイルだけ除外して残りを削除
    2. 最新N件だけ残して古いファイルを削除
  6. フォルダごと削除する(rd / rmdir)
    1. 基本: フォルダと中身をまとめて削除
    2. フォルダの中身だけ削除してフォルダ自体は残す
  7. 存在確認してから安全に削除する
  8. 実践例A: 30日より古いログを自動削除してレポートを残す
  9. 実践例B: 拡張子別に一括削除(複数拡張子対応)
  10. 実践例C: サイズ0のファイルを一括削除
  11. 実践例D: 削除ログをCSVに記録して安全に運用する
  12. 読み取り専用・隠しファイルを削除する
  13. よくある落とし穴
    1. 落とし穴1: 対象ファイルがゼロ件でもエラーと見なされる
    2. 落とし穴2: パスにスペースがある場合はダブルクォート必須
    3. 落とし穴3: ループ内で %ERRORLEVEL% は正しく更新されない
    4. 落とし穴4: rd /s /q で変数が空だとカレントまたは上位フォルダを削除する
    5. 落とし穴5: del はフォルダを削除できない(del でフォルダ指定するとエラー)
  14. よくある質問(FAQ)
  15. まとめ

del コマンドの構文と主なオプション

del [オプション] [ファイルパス]
erase [オプション] [ファイルパス]   ← del の別名

主なオプション:
  /Q   : 確認プロンプトを表示しない(Quiet)
  /F   : 読み取り専用ファイルも強制削除(Force)
  /S   : 指定フォルダ以下のサブフォルダも再帰的に削除
  /A:H : 隠し属性(Hidden)のファイルを対象にする
  /A:R : 読み取り専用(Read-only)属性のファイルを対象にする
  /A:S : システム属性のファイルを対象にする
  /P   : ファイルごとに削除確認を求める(対話モード)
操作 構文例 説明
単一ファイルを削除 del /Q "pathfile.txt" 確認なしで削除
拡張子一括削除 del /Q "path*.log" .log を全て削除
読み取り専用も削除 del /F /Q "path*.bak" 強制削除
サブフォルダも再帰削除 del /S /Q "path*.tmp" 全階層の .tmp を削除
フォルダごと削除 rd /s /q "folder" 中身ごとフォルダを削除
日付条件付き削除 forfiles /p path /m *.log /d -30 /c "cmd /c del @file" 30日以上古いファイルを削除

方法1: 単一ファイルを削除する

基本: 指定ファイルを削除

@echo off
setlocal

set TARGET=C:worklogsapp.log

rem ファイルが存在する場合のみ削除
if exist "%TARGET%" (
    del /Q "%TARGET%"
    if errorlevel 1 (
        echo [ERROR] 削除に失敗しました: %TARGET%
    ) else (
        echo [OK] 削除しました: %TARGET%
    )
) else (
    echo [SKIP] ファイルが存在しません: %TARGET%
)

endlocal

方法2: ワイルドカードで複数ファイルを一括削除

特定の拡張子をまとめて削除

@echo off
setlocal

set LOGDIR=C:worklogs

rem .log ファイルを全て削除(確認なし)
del /Q "%LOGDIR%*.log"

rem .tmp と .bak もまとめて削除
del /Q "%LOGDIR%*.tmp"
del /Q "%LOGDIR%*.bak"

echo 削除完了
endlocal

ファイル名パターンで絞り込んで削除

@echo off
setlocal

set LOGDIR=C:worklogs

rem "temp_" で始まるファイルを削除
del /Q "%LOGDIR%	emp_*.*"

rem "debug" を含む .log ファイルを削除
del /Q "%LOGDIR%*debug*.log"

endlocal

サブフォルダも含めて再帰的に削除

@echo off
setlocal

set WORKDIR=C:work

rem /S でサブフォルダも含めて全 .tmp を削除
del /S /Q "%WORKDIR%*.tmp"

echo サブフォルダを含む .tmp ファイルを削除しました
endlocal
del /S はフォルダ名を表示するが削除はしない
del /S /Q "*.tmp" を実行すると、削除したファイルが含まれていたフォルダ名が標準出力に表示されます。
これはエラーではなく仕様の動作です。>nul を付けるとフォルダ名の表示も抑制できます。
なお del /S はファイルを削除しますが、空になったフォルダは削除しません。

方法3: forfiles で日付条件付き削除

forfiles を使うと「N日以上古いファイルを削除」という日付条件を付けられます。ログ自動削除の定番パターンです。

30日より古いファイルを削除

@echo off
setlocal

set LOGDIR=C:worklogs

rem 更新日が30日以上前の .log ファイルを削除
forfiles /p "%LOGDIR%" /m *.log /d -30 /c "cmd /c del @file"

if errorlevel 1 (
    echo 対象ファイルなし(30日以内のファイルのみ)
) else (
    echo 古いログファイルを削除しました
)

endlocal

特定日付より前のファイルを削除

@echo off
setlocal

set LOGDIR=C:worklogs

rem 2025年1月1日より前の .log ファイルを削除
forfiles /p "%LOGDIR%" /m *.log /d 2025/01/01 /c "cmd /c del @file"

endlocal

サブフォルダも含めて古いファイルを削除

@echo off
setlocal

set LOGDIR=C:worklogs

rem /s でサブフォルダも対象にして60日以上古い .log を削除
forfiles /p "%LOGDIR%" /s /m *.log /d -60 /c "cmd /c del @file"

endlocal
forfiles の /d オプションは「更新日」を基準にする
forfiles /d -30 の基準は ファイルの最終更新日時 です。作成日ではない点に注意してください。
ログファイルが毎日追記されている場合、最終更新日は最新なので /d -30 の対象になりません。
日付付きファイル名で毎日ローテーションしているログには有効です。

方法4: for + del で柔軟なフィルタリング削除

for /fdir の出力を受け取り、条件を細かく制御して削除します。

特定のファイルだけ除外して残りを削除

@echo off
setlocal enabledelayedexpansion

set LOGDIR=C:worklogs

rem "keep_" で始まるファイルを除いて .log を削除
for %%F in ("%LOGDIR%*.log") do (
    echo %%~nxF | findstr /b "keep_" >nul
    if errorlevel 1 (
        del /Q "%%~fF"
        echo 削除: %%~nxF
    ) else (
        echo 保持: %%~nxF
    )
)

endlocal

最新N件だけ残して古いファイルを削除

@echo off
setlocal enabledelayedexpansion

set LOGDIR=C:worklogs
set KEEP=5

rem ファイル数を数える
set TOTAL=0
for %%F in ("%LOGDIR%*.log") do set /a TOTAL+=1

set /a DELETE_COUNT=%TOTAL%-%KEEP%

if !DELETE_COUNT! LEQ 0 (
    echo 削除不要: %TOTAL% ファイル(KEEP=%KEEP% 以内)
    goto :end
)

rem 更新日が古い順に並べて超過分を削除
set CNT=0
for /f "delims=" %%F in ('dir /b /a-d /o:d "%LOGDIR%*.log"') do (
    if !CNT! LSS !DELETE_COUNT! (
        del /Q "%LOGDIR%\%%F"
        echo 削除: %%F
        set /a CNT+=1
    )
)

echo 完了: !CNT! ファイルを削除しました
:end
endlocal

ログの世代管理・自動削除の実装詳細は バッチファイルでログローテーションを実装する方法 で詳しく解説しています。

フォルダごと削除する(rd / rmdir)

フォルダとその中身をまとめて削除するには rd(または rmdir)を使います。

基本: フォルダと中身をまとめて削除

@echo off
setlocal

set TARGET_DIR=C:work	mp

rem フォルダが存在する場合のみ削除
if exist "%TARGET_DIR%" (
    rem /s: サブフォルダも含む  /q: 確認なし
    rd /s /q "%TARGET_DIR%"
    if errorlevel 1 (
        echo [ERROR] フォルダ削除に失敗しました
    ) else (
        echo [OK] フォルダを削除しました: %TARGET_DIR%
    )
) else (
    echo [SKIP] フォルダが存在しません: %TARGET_DIR%
)

endlocal

フォルダの中身だけ削除してフォルダ自体は残す

@echo off
setlocal

set TARGET_DIR=C:work	mp

rem フォルダの中身(ファイルのみ)を削除
del /Q /F "%TARGET_DIR%*.*"

rem 中のサブフォルダも削除したい場合
for /d %%F in ("%TARGET_DIR%*") do (
    rd /s /q "%%~fF"
)

echo フォルダの中身を削除しました(フォルダ自体は残っています)
endlocal
rd /s /q はフォルダを完全削除する——復元不可
rd /s /q "フォルダ" は指定フォルダと中身を全て削除します。ゴミ箱に入らず、確認プロンプトも出ません。
特に変数でパスを組み立てる場合、変数が空文字になると意図しない上位フォルダを削除する恐れがあります。
変数が空でないことを if "%TARGET_DIR%"=="" で確認してから実行することを強く推奨します。

存在確認してから安全に削除する

@echo off
setlocal

set LOGDIR=C:worklogs

rem === 安全確認チェック ===

rem 1. 変数が空でないことを確認
if "%LOGDIR%"=="" (
    echo [ERROR] 削除対象パスが空です。処理を中止します
    exit /b 1
)

rem 2. 削除対象フォルダが存在することを確認
if not exist "%LOGDIR%" (
    echo [ERROR] フォルダが存在しません: %LOGDIR%
    exit /b 1
)

rem 3. 削除前に対象ファイルをリスト表示して確認
echo === 削除予定ファイル ===
dir /b "%LOGDIR%*.log" 2>nul
echo =======================

rem 4. 削除実行
del /Q "%LOGDIR%*.log"
echo [OK] 削除完了

endlocal

IF EXIST での存在確認の詳細は IF EXISTでファイル・フォルダの存在確認をする方法 を参照してください。

実践例A: 30日より古いログを自動削除してレポートを残す

@echo off
setlocal enabledelayedexpansion

set LOGDIR=C:worklogs
set REPORT=%~dp0delete_report.log
set DAYS=30

rem レポートヘッダー
(
    echo ===========================
    echo 削除実行日時: %DATE% %TIME%
    echo 対象フォルダ: %LOGDIR%
    echo 削除条件: %DAYS%日以上古いファイル
    echo ===========================
) >> "%REPORT%"

rem 削除前のファイル数を記録
set BEFORE=0
for %%F in ("%LOGDIR%*.log") do set /a BEFORE+=1

rem 古いファイルを削除(削除ファイル名もレポートに記録)
forfiles /p "%LOGDIR%" /m *.log /d -%DAYS% /c "cmd /c (echo 削除: @file >> "%~dp0delete_report.log"" ^& del @file)"

rem 削除後のファイル数を記録
set AFTER=0
for %%F in ("%LOGDIR%*.log") do set /a AFTER+=1

set /a DELETED=%BEFORE%-%AFTER%

echo 削除件数: !DELETED! >> "%REPORT%"
echo. >> "%REPORT%"

echo 削除完了: %BEFORE% → !AFTER! ファイル(!DELETED! 件削除)
endlocal

実践例B: 拡張子別に一括削除(複数拡張子対応)

@echo off
setlocal enabledelayedexpansion

set CLEANDIR=C:work	mp

rem 削除する拡張子のリスト
for %%E in (tmp bak log~ ~tmp cache) do (
    set COUNT=0
    for %%F in ("%CLEANDIR%*.%%E") do set /a COUNT+=1

    if !COUNT! GTR 0 (
        del /Q "%CLEANDIR%*.%%E"
        echo .%%E を !COUNT! ファイル削除しました
    ) else (
        echo .%%E ファイルなし(スキップ)
    )
)

endlocal

実践例C: サイズ0のファイルを一括削除

@echo off
setlocal

set TARGETDIR=C:worklogs

rem ファイルサイズが 0 バイトのファイルを全て削除
for %%F in ("%TARGETDIR%*.*") do (
    if %%~zF == 0 (
        del /Q "%%~fF"
        echo 空ファイル削除: %%~nxF
    )
)

endlocal

ファイルサイズを条件に使う詳細は バッチファイルでファイルサイズを取得して条件分岐する方法 を参照してください。

実践例D: 削除ログをCSVに記録して安全に運用する

@echo off
setlocal enabledelayedexpansion

set LOGDIR=C:worklogs
set CSVLOG=%~dp0delete_history.csv

rem ヘッダー(初回のみ)
if not exist "%CSVLOG%" (
    echo 日時,ファイル名,サイズ(bytes),削除結果 > "%CSVLOG%"
)

for %%F in ("%LOGDIR%*.log") do (
    set FNAME=%%~nxF
    set FSIZE=%%~zF

    del /Q "%%~fF"
    if not errorlevel 1 (
        set RESULT=OK
    ) else (
        set RESULT=FAIL
    )

    echo %DATE% %TIME%,!FNAME!,!FSIZE!,!RESULT! >> "%CSVLOG%"
    echo !RESULT!: !FNAME!
)

endlocal

読み取り専用・隠しファイルを削除する

@echo off
setlocal

set TARGETDIR=C:work	mp

rem /F : 読み取り専用属性のファイルも強制削除
del /F /Q "%TARGETDIR%*.bak"

rem /A:H : 隠し属性のファイルを削除
del /A:H /Q "%TARGETDIR%*.*"

rem /F /A:H /A:S : 読み取り専用・隠し・システム属性をすべて削除
del /F /A:H /A:S /Q "%TARGETDIR%*.*"

endlocal
/A オプションは複数指定できる
/A:H(隠し)、/A:R(読み取り専用)、/A:S(システム)は組み合わせて指定できます。
/A:-H のように - を付けると「その属性を持たないファイル」を対象にできます。
例: del /A:-H /Q = 隠し属性を持たない通常ファイルのみ削除

よくある落とし穴

落とし穴1: 対象ファイルがゼロ件でもエラーと見なされる

rem del は削除対象が1件もないと "ファイルが見つかりません" を表示し
rem ERRORLEVEL=1 を返す
rem → "真のエラー" と区別するには削除前に存在確認する

if exist "%LOGDIR%*.log" (
    del /Q "%LOGDIR%*.log"
    echo 削除完了
) else (
    echo 削除対象ファイルなし
)

落とし穴2: パスにスペースがある場合はダブルクォート必須

rem NG: スペースを含むパスをクォートなしで指定するとエラー
del C:My Folder*.log
rem → "C:My" と "Folder*.log" に分断される

rem OK: ダブルクォートで囲む
del /Q "C:My Folder*.log"

落とし穴3: ループ内で %ERRORLEVEL% は正しく更新されない

rem NG: for ブロック内で %ERRORLEVEL% を参照すると古い値のまま
@echo off
setlocal
for %%F in (*.log) do (
    del "%%F"
    if %ERRORLEVEL% == 0 echo OK  ← 常に0になる可能性がある
)

rem OK: if errorlevel を使う(%ERRORLEVEL% 変数を参照しない)
@echo off
setlocal
for %%F in (*.log) do (
    del "%%F"
    if not errorlevel 1 echo OK: %%F
    if errorlevel 1 echo FAIL: %%F
)

落とし穴4: rd /s /q で変数が空だとカレントまたは上位フォルダを削除する

rem 危険な例: TARGET_DIR が空だった場合
set TARGET_DIR=
rd /s /q "%TARGET_DIR%"   ← "rd /s /q """ と解釈される場合がある

rem 必ず変数の空チェックを行ってから実行
if "%TARGET_DIR%"=="" (
    echo [ERROR] 削除対象パスが空です。処理を中止します
    exit /b 1
)
rd /s /q "%TARGET_DIR%"

落とし穴5: del はフォルダを削除できない(del でフォルダ指定するとエラー)

rem NG: del でフォルダを指定してもフォルダは削除されない
del /Q "C:work	mp"   ← フォルダなので何もしない(またはエラー)

rem OK: フォルダの削除は rd を使う
rd /s /q "C:work	mp"

rem フォルダの中身(ファイル)だけ削除してフォルダ自体を残したい場合
del /Q "C:work	mp*.*"

よくある質問(FAQ)

Q 削除したファイルを復元できますか?
A

del コマンドで削除したファイルはゴミ箱を経由しないため、通常は復元できません。ファイルが上書きされる前であればディスク復元ツール(Recuva 等)で回復できる場合がありますが、確実性はありません。重要なファイルは削除前にバックアップを取ることを強く推奨します。

rem 削除前にバックアップを取るパターン
set SRC=C:worklogs
set BAK=C:worklogs_backup

if not exist "%BAK%" mkdir "%BAK%"
xcopy "%SRC%*.log" "%BAK%" /Y >nul

del /Q "%SRC%*.log"
echo バックアップ後に削除しました
Q 削除する件数が多い場合の進捗を表示したい
A

for ループ内でカウンタを使って進捗を表示できます。

@echo off
setlocal enabledelayedexpansion

set LOGDIR=C:worklogs

rem 総数を先に数える
set TOTAL=0
for %%F in ("%LOGDIR%*.log") do set /a TOTAL+=1

rem 削除しながら進捗表示
set CNT=0
for %%F in ("%LOGDIR%*.log") do (
    del /Q "%%~fF"
    set /a CNT+=1
    echo [!CNT!/%TOTAL%] 削除: %%~nxF
)

echo 完了: !CNT! ファイルを削除しました
endlocal
Q 特定の文字列を含むファイル名のファイルだけ削除したい
A

forfindstr を組み合わせてファイル名を絞り込みます。

@echo off
setlocal

set LOGDIR=C:worklogs

rem ファイル名に "error" を含む .log ファイルだけ削除
for %%F in ("%LOGDIR%*.log") do (
    echo %%~nxF | findstr /i "error" >nul
    if not errorlevel 1 (
        del /Q "%%~fF"
        echo 削除: %%~nxF
    )
)

endlocal

ファイル名に含まない文字列での削除は ファイル名に指定文字列を含まないファイルを削除する方法 も参照してください。

Q タスクスケジューラで定期的に古いファイルを削除したい
A

削除スクリプトをタスクスケジューラに登録します。

rem 毎日深夜2時に実行するタスクを登録(管理者権限で実行)
schtasks /create /tn "AutoDeleteOldLogs" ^
  /tr "cmd /c "C:atchdelete_old_logs.bat"" ^
  /sc daily /st 02:00 /ru "%USERNAME%" /f

rem 登録確認
schtasks /query /tn "AutoDeleteOldLogs" /fo list

rem タスクを削除する場合
schtasks /delete /tn "AutoDeleteOldLogs" /f
Q 削除前にユーザーに確認を求めたい
A

set /p で入力を受け取り、Y/N で分岐します。

@echo off
setlocal

set LOGDIR=C:worklogs

rem 削除予定ファイルを表示
echo 以下のファイルを削除します:
dir /b "%LOGDIR%*.log" 2>nul
echo.

rem 確認入力
set /p CONFIRM=続行しますか? (Y/N): 

if /i "%CONFIRM%"=="Y" (
    del /Q "%LOGDIR%*.log"
    echo 削除しました
) else (
    echo キャンセルしました
)

endlocal

まとめ

目的 推奨方法
単一ファイルを削除 del /Q "pathfile.txt"
拡張子一括削除 del /Q "path*.log"
読み取り専用も強制削除 del /F /Q "path*.bak"
サブフォルダも再帰削除 del /S /Q "path*.tmp"
フォルダごと削除 rd /s /q "folder"
日付条件付き削除 forfiles /p path /m *.log /d -30 /c "cmd /c del @file"
最新N件だけ残す dir /o:d + for /f + del
特定文字列を含むファイル削除 for + findstr + del
安全な削除(空チェック付き) 削除前に変数チェック・if exist 確認

ファイルの移動については ファイルを別フォルダに移動する方法完全ガイド を、ログの世代管理・自動削除の実装詳細は バッチファイルでログローテーションを実装する方法 を参照してください。