バッチファイルで del コマンドを実行したとき、「アクセスが拒否されました」というエラーで削除できないケースがあります。このエラーは「管理者権限が足りない」だけが原因ではなく、ファイルのロック・読み取り専用属性・NTFS ACL・所有権・パスの形式など複数の要因が絡みます。本記事では原因を 7 つに分類し、それぞれ具体的なコードと共に解決策を解説します。
原因の全体像
| 原因 | 典型的な症状 | 主な対処 |
|---|---|---|
| ファイルが使用中(プロセスロック) | アプリ実行中に削除しようとする | プロセス終了 or 再起動後に削除 |
| 管理者権限不足 | System32・Program Files 配下の削除 | 管理者として実行・自己昇格 |
| 読み取り専用属性 | attrib で R 属性が付いている | attrib -r で属性解除 |
| ACL(アクセス制御リスト)の拒否設定 | icacls で Deny エントリがある | icacls /grant または takeown |
| TrustedInstaller / SYSTEM 所有権 | OS コンポーネントファイル | takeown + icacls /grant |
| ファイル名・パスの問題 | 末尾スペース・特殊文字・長いパス | PowerShell -LiteralPath・\\?\プレフィックス |
| ネットワーク共有の制限 | UNC パス先の権限不足 | net use で認証・共有設定の確認 |
原因①:ファイルが使用中(プロセスロック)
アプリケーションやサービスがファイルを開いたままにしていると、削除はブロックされます。ログファイル・DLL・設定ファイルなどで起きやすいです。まずどのプロセスがロックしているかを特定します。
rem Sysinternals の handle.exe を使ってロック元を確認 handle.exe "C:\app\log.txt" rem または Resource Monitor(タスクマネージャー→パフォーマンス→リソースモニターを開く) rem CPU タブ → 「関連付けられたハンドルの検索」にファイル名を入力
@echo off
rem アプリを停止してから削除する
taskkill /f /im "myapp.exe" >nul 2>&1
timeout /t 2 >nul
del "C:\app\log.txt"
if errorlevel 1 (
echo 削除失敗: まだロックされている可能性があります
) else (
echo 削除成功
)
@echo off
net session >nul 2>&1 || goto :no_admin
sc stop MyService >nul 2>&1
set /a W=0
:wait
sc query MyService | findstr /i "STOPPED" >nul 2>&1
if errorlevel 1 (
timeout /t 2 >nul & set /a W+=2
if %W% lss 30 goto :wait
echo タイムアウト & exit /b 1
)
del "C:\app\locked_file.dat"
sc start MyService >nul 2>&1
goto :eof
:no_admin
echo 管理者権限が必要です
exit /b 1
再起動後に削除したい場合は、Windows の「保留中の削除」機能(PendingFileRenameOperations)を使う方法もありますが、レジストリを直接操作するため注意が必要です。再起動が許容できる環境では、単純に再起動後に削除するのが最も確実です。
原因②:管理者権限不足
C:\Windows・C:\Program Files 配下など、OS が保護している領域のファイルは管理者権限なしでは削除できません。バッチを「管理者として実行」するか、自己昇格コードを組み込みます。
@echo off
net session >nul 2>&1
if errorlevel 1 (
echo 管理者権限が必要です。再起動します...
powershell -NoProfile -Command ^
"Start-Process -FilePath '%~f0' -ArgumentList '%*' -WorkingDirectory '%CD%' -Verb RunAs"
exit /b
)
echo 管理者権限を確認しました。
del "C:\Program Files\OldApp\unneeded.dll"
管理者権限が必要な処理の詳細はバッチファイルで管理者権限が必要な処理が失敗するときの完全解決ガイドをあわせて参照してください。
原因③:読み取り専用属性
ファイルに読み取り専用(R)・システム(S)・隠し(H)属性が付いていると、del はエラーを返します。attrib コマンドで属性を確認し、解除してから削除します。
@echo off rem 属性を確認 attrib "C:\data\sample.txt" rem 読み取り専用・システム・隠し属性をすべて解除 attrib -r -s -h "C:\data\sample.txt" del "C:\data\sample.txt" rem フォルダ内を再帰的に解除してから削除 attrib -r -s -h "C:\data\*" /s /d rd /s /q "C:\data"
del /a オプションを使うと、属性を無視して削除を試みることができます。del /a:r で読み取り専用ファイルのみを対象にすることも可能です。
rem /a:rhs で読み取り専用・隠し・システム属性のファイルも削除対象に del /f /q /a:rhs "C:\data\locked.tmp" rem /f は強制削除(読み取り専用も含む) del /f /q "C:\data\sample.txt"
原因④:ACL(アクセス制御リスト)の拒否設定
NTFSのアクセス許可で「削除の拒否」エントリが設定されていると、管理者権限でも削除が失敗します。icacls で権限を確認し、許可を付与します。
@echo off rem 現在の権限を確認 icacls "C:\data\sample.txt" rem 現在のユーザーにフルコントロールを付与 icacls "C:\data\sample.txt" /grant "%USERNAME%":F del "C:\data\sample.txt" rem フォルダ全体の権限をリセットして継承に戻す icacls "C:\data" /reset /t /c
icacls の出力に D:AI(Deny)エントリが含まれている場合は拒否エントリを削除する必要があります。icacls "ファイル" /remove:d "%USERNAME%" で拒否エントリを取り除けます。
原因⑤:TrustedInstaller / SYSTEM の所有権
Windowsシステムファイルの多くは所有者が TrustedInstaller に設定されており、管理者でも通常は削除・変更できません。所有権を取得してから権限を付与する必要があります。
@echo off net session >nul 2>&1 || goto :no_admin set "TARGET=C:\Windows\System32\sample.dll" rem 所有権を現在の管理者ユーザーに取得 takeown /f "%TARGET%" /a rem 管理者グループにフルコントロールを付与 icacls "%TARGET%" /grant Administrators:F rem 削除 del /f "%TARGET%" goto :eof :no_admin echo 管理者権限が必要です exit /b 1
原因⑥:ファイル名・パスの問題
末尾にスペースやピリオドが付いたファイル名、特殊文字を含む名前、260文字を超えるパスなど、通常の del では処理できないファイルが存在します。これらは PowerShell の-LiteralPath や \\?\ プレフィックスで対処します。
rem 末尾にスペースやピリオドが付いたファイルの削除 powershell -NoProfile -Command "Remove-Item -LiteralPath 'C:\data\oddname. ' -Force" rem 特殊文字([ ] ` など)を含むファイル名 powershell -NoProfile -Command "Remove-Item -LiteralPath 'C:\data\file[1].txt' -Force" rem NUL や CON などの予約デバイス名ファイル(\\?\ が必要) del "\\?\C:\data\NUL.txt"
rem \\?\ プレフィックスで 260 文字制限を回避 del "\\?\C:\very\long\path\to\a\deeply\nested\file.txt" rem robocopy で空フォルダを同期して中身を消す(長パス対応) md "%TEMP%\empty_tmp" robocopy "%TEMP%\empty_tmp" "C:\deep\nested\folder" /purge /mir >nul 2>&1 rd /s /q "C:\deep\nested\folder" rd "%TEMP%\empty_tmp"
パス長制限の詳細はWindowsのパス長制限(MAX_PATH=260)完全攻略を参照してください。
原因⑦:ネットワーク共有の制限
UNCパスやマップドドライブ経由のファイルは、共有フォルダ側のアクセス権限が影響します。ローカルで管理者権限を持っていても、ネットワーク先で権限がなければ削除できません。
@echo off rem 認証情報を指定して接続 net use "\\server\share" /user:DOMAIN\User パスワード rem UNCパスで削除 del "\\server\share\oldfile.txt" rem 接続を切断 net use "\\server\share" /delete >nul 2>&1
PowerShell を使ったより強力な削除
cmd の del が対処しにくいケースでは PowerShell の Remove-Item が有効です。-Force で読み取り専用・隠し属性を無視し、-LiteralPath で特殊文字を含むパスも正確に指定できます。
@echo off
rem 単ファイル削除(強制)
powershell -NoProfile -Command "Remove-Item -LiteralPath 'C:\data\file.txt' -Force"
rem フォルダごと再帰削除
powershell -NoProfile -Command "Remove-Item -LiteralPath 'C:\data\old_folder' -Recurse -Force"
rem エラー情報を確認しながら削除
powershell -NoProfile -Command ^
"try { Remove-Item -LiteralPath 'C:\data\file.txt' -Force } catch { Write-Host $_.Exception.Message }"
削除の再試行パターン
一時的なロックの場合、少し待ってから再試行すると削除できることがあります。ウイルス対策ソフトがファイルを一時的にスキャンしているケースなど、数秒待つだけで解消することがあります。
@echo off
setlocal EnableDelayedExpansion
set "TARGET=C:\data\target.txt"
set /a RETRY=0
:del_try
del /f /q "%TARGET%" 2>nul
if exist "%TARGET%" (
set /a RETRY+=1
if !RETRY! lss 5 (
echo リトライ !RETRY!/5... ロックが解除されるのを待機中
timeout /t 2 >nul
goto :del_try
)
echo 削除失敗: "%TARGET%" はロックされたままです
exit /b 1
)
echo 削除成功: "%TARGET%"
endlocal
exit /b 0
原因別チェックフロー
| 確認順序 | 確認方法 | 対処 |
|---|---|---|
| ①ファイルが使用中か | handle.exe / Resource Monitor で確認 | プロセス終了 → 再削除 |
| ②管理者権限があるか | net session でチェック |
管理者として実行 |
| ③読み取り専用属性か | attrib ファイル名 で確認 |
attrib -r -s -h → 再削除 |
| ④ACL で拒否されているか | icacls ファイル名 で Deny エントリ確認 |
拒否エントリ削除 → 再削除 |
| ⑤所有者が TrustedInstaller か | icacls の出力で Owner 確認 |
takeown + icacls /grant → 再削除 |
| ⑥パス・ファイル名に問題があるか | 末尾スペース・特殊文字・260文字超えを確認 | PowerShell -LiteralPath / \\?\ を使う |
| ⑦ネットワーク上のファイルか | UNC パスまたはマップドドライブか確認 | net use で認証 → 再削除 |
よくある質問
/f は読み取り専用属性のファイルを強制削除するオプションですが、プロセスロックや ACL の拒否設定には効きません。まずロック元プロセスを特定し、必要に応じて icacls で権限を付与してください。robocopy 空フォルダ 対象フォルダ /purge で中身を空にしてから rd すると回避できる場合があります。takeown /f ファイル の後に必ず icacls ファイル /grant Administrators:F を実行して、フルコントロールの権限を追加してください。sc stop サービス名 で停止してから削除します。まとめ
「アクセスが拒否されました」の原因は 1 つではありません。次の順で確認するのが最短経路です。
- ファイルが別プロセスに使われていないか →
handle.exeや Resource Monitor で確認 - 管理者権限があるか →
net sessionでチェック、なければ自己昇格 - 読み取り専用・システム属性がないか →
attrib -r -s -hで解除 - ACL に Deny エントリがないか →
icaclsで確認・削除 - TrustedInstaller 所有か →
takeown + icacls /grant - ファイル名・パスに問題があるか → PowerShell
-LiteralPathまたは\\?\

