バッチファイルで「アクセスが拒否されました(Access is denied.)」が出たとき、原因はひとつではありません。管理者権限の不足・ACL設定ミス・他プロセスによるファイルロック・読み取り専用属性・保護フォルダへの書き込みなど、様々な原因が考えられます。
この記事では原因別に対策を体系的に解説し、バッチファイル内でエラーを適切にハンドリングする実践パターンまで紹介します。
- 「アクセスが拒否されました」が発生する8つの原因と見分け方
- 管理者権限での実行方法(右クリック・スクリプト自己昇格)
- icacls でファイル・フォルダの権限(ACL)を修正する方法
- ファイルロックの確認と解除(taskkill・待機)
- 読み取り専用属性の解除(attrib)
- 保護フォルダへの書き込み回避策
- ERRORLEVEL を使ったエラーハンドリングとリトライ
- 落とし穴5選・実践例3本・FAQ6問
1. 原因別早見表
まず「どの操作をしたときにエラーが出るか」で原因を絞り込みましょう。
| 操作・状況 | 主な原因 | 対策セクション |
|---|---|---|
| レジストリ操作・サービス起停止・システムフォルダへの書き込み | 管理者権限の不足 | → 2節 |
| 特定フォルダへのコピー・削除ができない | ACL(アクセス制御リスト)の設定不足 | → 3節 |
| 使用中のファイルを削除・上書きできない | 他プロセスによるファイルロック | → 4節 |
| ファイルを編集・削除できない | 読み取り専用属性が設定されている | → 5節 |
| C:\Windows や C:\Program Files への書き込みが失敗 | 保護フォルダへの直接書き込み | → 6節 |
| ネットワーク共有フォルダへの操作が失敗 | ネットワーク権限・認証の問題 | → 7節 |
| 長いパスや日本語・特殊文字を含むパスで失敗 | パス・文字列の問題 | → 8節 |
| タスクスケジューラから実行したときだけ失敗 | 実行ユーザー・権限の違い | → 9節 |
2. 管理者権限の不足が原因の場合
もっとも多い原因です。レジストリ操作・Windowsサービスの起動停止・システムフォルダへの書き込みなど、管理者権限が必要な操作はバッチを「管理者として実行」しないと失敗します。
2-1. 手動で管理者として実行する
バッチファイルを右クリック → 「管理者として実行」で実行します。
2-2. バッチ自身が管理者権限で動いているか確認する
@echo off
:: 管理者権限チェック
net session >nul 2>&1
if errorlevel 1 (
echo [ERROR] このスクリプトは管理者権限で実行してください
echo 右クリック → 管理者として実行 を選んでください
pause
exit /b 1
)
echo [OK] 管理者権限で実行中です
2-3. バッチが自動的に管理者権限を要求する(UAC昇格)
詳細は バッチファイルで管理者権限を自動取得する方法 と 管理者権限で自動実行するバッチファイルの作り方 を参照してください。
@echo off
:: 管理者権限チェック → なければ UAC 昇格して自己再実行
net session >nul 2>&1
if errorlevel 1 (
echo 管理者権限が必要です。UAC プロンプトが表示されます...
powershell -NoProfile -Command "Start-Process cmd -ArgumentList '/c "%~f0"' -Verb RunAs"
exit /b
)
:: ここから本処理(管理者権限あり)
echo [OK] 管理者として実行しています
pause
3. ACL(アクセス権限)不足が原因の場合
ファイルやフォルダの NTFS アクセス制御リスト(ACL)で操作に必要な権限が与えられていない場合です。管理者権限が必要な処理が失敗するときの解決策 も参照してください。
3-1. icacls で現在の権限を確認する
:: 対象フォルダの権限を表示 icacls "C:\work\target" :: 出力例: :: C:\work\target BUILTIN\Administrators:(I)(OI)(CI)(F) :: NT AUTHORITY\SYSTEM:(I)(OI)(CI)(F) :: BUILTIN\Users:(I)(OI)(CI)(RX) :: ↑ Users はRX(読み取り・実行のみ)= 書き込みができない
3-2. icacls で権限を付与する
@echo off
:: 現在のユーザーにフルコントロールを付与
icacls "C:\work\target" /grant "%USERNAME%":(F) /t
if errorlevel 1 (
echo [ERROR] 権限の変更に失敗しました(管理者権限が必要です)
exit /b 1
)
echo [OK] フルコントロール権限を付与しました
:: 代表的な権限フラグ
:: (F) フルコントロール
:: (M) 変更(書き込み・削除可)
:: (RX) 読み取り・実行
:: (R) 読み取りのみ
:: /t サブフォルダ・ファイルにも再帰適用
3-3. 一時的に権限を取得してから元に戻す
@echo off setlocal set "TARGET=C:\work\protected_dir" :: 権限を追加 icacls "%TARGET%" /grant "%USERNAME%":(F) /t >nul :: 操作を実行 xcopy /e /y "C:\src\*" "%TARGET%\" >nul :: 権限を元に戻す(付与した権限を削除) icacls "%TARGET%" /remove "%USERNAME%" /t >nul echo 処理完了(権限を元に戻しました)
4. ファイルロックが原因の場合
ほかのプロセスがファイルを開いている(ロックしている)と、削除・上書きができません。
4-1. ロックしているプロセスを確認する
:: tasklist でプロセス一覧を確認(特定のプロセス名を検索) tasklist /fi "imagename eq notepad.exe" :: 詳細なロック情報は Sysinternals の handle.exe が便利(別途インストール必要) :: handle.exe "C:\work\locked_file.txt"
4-2. プロセスを終了してからファイル操作する
@echo off
setlocal
set "TARGET_FILE=C:\work\data.log"
:: notepad.exe が開いていれば強制終了
tasklist /fi "imagename eq notepad.exe" 2>nul | find "notepad.exe" >nul
if not errorlevel 1 (
echo notepad.exe を終了します...
taskkill /f /im notepad.exe >nul 2>&1
timeout /t 2 /nobreak >nul
)
:: ファイル操作
del "%TARGET_FILE%" >nul 2>&1
if errorlevel 1 (
echo [ERROR] ファイルを削除できません(まだロック中の可能性があります)
exit /b 1
)
echo [OK] 削除しました
プロセス終了の詳細は プロセスの終了を待つ全方法まとめ も参照してください。
4-3. リトライループで待機する
プロセスがファイルを解放するのを待つ場合は、一定間隔でリトライします。
@echo off
setlocal
set "TARGET=C:\work\output.log"
set "MAX_RETRY=10"
set "WAIT_SEC=3"
:retry
del "%TARGET%" >nul 2>&1
if not errorlevel 1 (
echo [OK] ファイルを削除しました
exit /b 0
)
set /a MAX_RETRY-=1
if %MAX_RETRY% LEQ 0 (
echo [ERROR] リトライ上限に達しました。ファイルがロックされています。
exit /b 1
)
echo [WAIT] ファイルがロック中。%WAIT_SEC% 秒後にリトライします(残り %MAX_RETRY% 回)
timeout /t %WAIT_SEC% /nobreak >nul
goto :retry
5. 読み取り専用属性が原因の場合
ファイルに読み取り専用属性(readonly)が設定されていると、上書き・削除ができません。
5-1. 属性を確認する
:: attrib コマンドで属性を確認 attrib "C:\work\config.ini" :: 出力例: :: A R C:\work\config.ini :: R = 読み取り専用(Read-only)が設定されている :: A = アーカイブ属性
5-2. 読み取り専用属性を解除してから操作する
@echo off
setlocal
set "TARGET=C:\work\config.ini"
:: 読み取り専用属性を解除(-R)
attrib -r "%TARGET%"
:: 操作実行
del "%TARGET%" >nul 2>&1
if errorlevel 1 (
echo [ERROR] 削除に失敗しました
exit /b 1
)
echo [OK] 削除しました
:: フォルダ配下すべての読み取り専用を解除
attrib -r "C:\work\*" /s /d
ファイル削除の詳細は ファイルを削除する方法完全ガイド と ファイル削除で「アクセスが拒否されました」が出るときの対策 も参照してください。
6. 保護フォルダへの書き込みが原因の場合
C:\Windows・C:\Program Files・C:\ProgramData などの保護フォルダは、管理者権限があっても直接操作できないケースがあります。
6-1. 一時フォルダや AppData を使う
@echo off setlocal :: 保護フォルダへの書き込みはNG → %TEMP% や %APPDATA% を使う set "WORK_DIR=%TEMP%\myapp_%RANDOM%" mkdir "%WORK_DIR%" :: 作業フォルダで処理 echo 設定内容 > "%WORK_DIR%\config.txt" :: 完了後に作業フォルダを削除 rd /s /q "%WORK_DIR%" echo 処理完了
6-2. rd でフォルダ削除できないとき
@echo off :: 通常の rd で失敗する場合は robocopy で空フォルダと同期する方法 set "TARGET=C:\work\stuck_folder" :: 空フォルダを作成して robocopy でミラーリング(実質フォルダを空にする) set "EMPTY=%TEMP%\empty_%RANDOM%" mkdir "%EMPTY%" robocopy "%EMPTY%" "%TARGET%" /mir >nul rd /s /q "%EMPTY%" rd /s /q "%TARGET%" echo [OK] フォルダを削除しました
フォルダ削除の詳細は バッチファイルでフォルダを削除する方法 も参照してください。
7. ネットワーク共有フォルダが原因の場合
@echo off
setlocal
set "SHARE=\\server\share"
:: 共有フォルダへの接続確認
net use "%SHARE%" >nul 2>&1
if errorlevel 1 (
echo [INFO] 共有フォルダに接続します...
net use "%SHARE%" /user:DOMAIN\username password >nul 2>&1
if errorlevel 1 (
echo [ERROR] 共有フォルダへの接続に失敗しました
exit /b 1
)
)
:: アクセス可能か確認してから操作
if not exist "%SHARE%\" (
echo [ERROR] 共有フォルダが見つかりません
exit /b 1
)
copy "C:\local\data.csv" "%SHARE%\data.csv" >nul
if errorlevel 1 (
echo [ERROR] 共有フォルダへのコピーに失敗しました
exit /b 1
)
echo [OK] コピー完了
8. パス・文字列の問題が原因の場合
スペースや特殊文字を含むパスは引用符で囲まないと「アクセスが拒否されました」と同様のエラーになります。パスにスペースが含まれているとエラーになるときの解決策 も参照してください。
:: NG: スペースを含むパスを引用符なしで使う copy C:\my folder\file.txt D:\output\ :: → "my" を別のコマンド引数として解釈してアクセス拒否 :: OK: 必ず引用符で囲む copy "C:\my folder\file.txt" "D:\output\" :: NG: 変数に格納したパスも引用符が必要 set SRC=C:\my folder\file.txt copy %SRC% "D:\output\" :: OK: 変数展開も引用符で保護 set "SRC=C:\my folder\file.txt" copy "%SRC%" "D:\output\"
9. タスクスケジューラから実行したときだけ失敗する場合
タスクスケジューラのタスク設定で実行ユーザーが違う、または「最上位の特権で実行する」にチェックが入っていないことが原因です。
:: タスクスケジューラで管理者権限が必要なタスクを登録する場合 :: schtasks コマンドで /RL HIGHEST (最上位権限)を指定 schtasks /create /tn "MyAdminTask" /tr "cmd /c C:\work\admin_task.bat" /sc daily /st 08:00 /ru SYSTEM /rl highest :: または既存タスクの実行レベルを変更 schtasks /change /tn "MyTask" /ru SYSTEM /rl highest
詳細は 管理者権限で自動実行するバッチファイルの作り方 を参照してください。
10. ERRORLEVEL によるエラーハンドリングとリトライ
アクセス拒否エラーを検知して適切にハンドリングするパターンです。ERRORLEVELを使ったエラーハンドリング も参照してください。
@echo off
setlocal
set "SRC=C:\work\source"
set "DST=D:\backup\dest"
:: 事前チェック
if not exist "%SRC%\" (
echo [ERROR] コピー元が見つかりません: %SRC%
exit /b 1
)
:: 読み取り専用を解除してからコピー
attrib -r "%SRC%\*" /s >nul 2>&1
:: 出力先を作成
if not exist "%DST%\" mkdir "%DST%"
:: コピー実行
xcopy /e /y "%SRC%\*" "%DST%\" >nul 2>&1
if errorlevel 1 (
echo [ERROR] コピーに失敗しました(errorlevel=%ERRORLEVEL%)
echo 考えられる原因:
echo 1. 出力先への書き込み権限がない → icacls で確認
echo 2. ファイルがロック中 → 使用中のアプリを終了
echo 3. 管理者権限が必要 → 管理者として再実行
exit /b 1
)
echo [OK] コピー完了: %DST%
11. 落とし穴5選と対策
落とし穴1:net session で管理者チェックするとドメイン環境でFalseになることがある
:: net session はドメイン環境や特定の構成で正しく動作しない場合がある
net session >nul 2>&1
:: より確実な方法: fltMC.exe を使って権限確認
fltMC >nul 2>&1
if errorlevel 1 (
echo 管理者権限がありません
) else (
echo 管理者権限があります
)
落とし穴2:icacls のパスに末尾の \ を付けるとエラーになる
:: NG: フォルダパスに末尾の \ を付けると構文エラー icacls "C:\work\target\" /grant Users:(F) :: OK: 末尾の \ を付けない icacls "C:\work\target" /grant Users:(F)
落とし穴3:rd /s /q でも「アクセスが拒否されました」が出る場合
:: 原因: フォルダ内に読み取り専用・ロック中のファイルが存在する :: 対策1: attrib で読み取り専用をすべて解除してから rd attrib -r -s "C:\work\target\*" /s /d rd /s /q "C:\work\target" :: 対策2: takeown でフォルダの所有権を取得してから削除 takeown /f "C:\work\target" /r /d y >nul icacls "C:\work\target" /grant "%USERNAME%":(F) /t >nul rd /s /q "C:\work\target"
落とし穴4:UAC昇格後にカレントディレクトリが変わる
:: UAC昇格(powershell Start-Process RunAs)後は
:: カレントディレクトリが C:\Windows\System32 になることがある
:: 対策: バッチのパスを %~dp0 で保存して明示的に使う
@echo off
:: バッチのあるフォルダに移動
cd /d "%~dp0"
net session >nul 2>&1
if errorlevel 1 (
powershell -NoProfile -Command "Start-Process cmd -ArgumentList '/c cd /d "%~dp0" && "%~f0"' -Verb RunAs"
exit /b
)
:: 管理者権限あり・%~dp0 にいる状態で処理
echo [OK] %CD%
落とし穴5:エラーメッセージが英語(”Access is denied.”)で出る場合
:: Windows の言語設定によってはエラーメッセージが英語で出る
:: find コマンドでメッセージ内容を判定するのは不安定
:: → ERRORLEVEL を使って判定するのが確実
copy "C:\work\test.txt" "C:\Windows\" >nul 2>&1
if errorlevel 1 (
echo アクセス拒否またはコピー失敗(errorlevel=%ERRORLEVEL%)
)
:: NG: find でエラーメッセージを拾おうとするのは言語依存で不安定
:: copy ... 2>&1 | find "拒否" はロケールによって動かない
12. 実践例3本
実践例1:管理者権限チェック付き一括ファイルコピースクリプト
@echo off
setlocal enabledelayedexpansion
:: ── 管理者権限チェック ──
net session >nul 2>&1
if errorlevel 1 (
echo 管理者権限が必要です。昇格します...
powershell -NoProfile -Command "Start-Process cmd -ArgumentList '/c "%~f0"' -Verb RunAs"
exit /b
)
set "SRC=C:\deploy\app"
set "DST=C:\Program Files\MyApp"
set "LOG=C:\work\deploy.log"
echo [%date% %time%] デプロイ開始 >> "%LOG%"
:: 宛先フォルダが存在しなければ作成
if not exist "%DST%\" mkdir "%DST%"
:: 読み取り専用属性を解除
attrib -r "%DST%\*" /s >nul 2>&1
:: コピー実行
xcopy /e /y "%SRC%\*" "%DST%\" >> "%LOG%" 2>&1
if errorlevel 1 (
echo [ERROR] コピー失敗。ログ: %LOG%
exit /b 1
)
echo [%date% %time%] デプロイ完了 >> "%LOG%"
echo [OK] %DST% にデプロイしました
実践例2:ファイル削除リトライ付き安全削除スクリプト
FOR ループ内から goto するとループが終了するため、サブルーチン(call)を使ってリトライを実装します。
@echo off
setlocal enabledelayedexpansion
set "TARGET_DIR=C:\work\logs"
set "MAX_RETRY=5"
set "WAIT_SEC=5"
set "DELETED=0"
set "FAILED=0"
:: FOR ループ内で goto するとループが終了するため call でサブルーチンを呼ぶ
for %%F in ("%TARGET_DIR%\*.log") do (
call :delete_with_retry "%%F"
)
echo ===== 結果: 削除 !DELETED! 件 / 失敗 !FAILED! 件 =====
if !FAILED! GTR 0 exit /b 1
exit /b 0
:delete_with_retry
set "FILE=%~1"
set "RETRY=0"
:del_retry
del "%FILE%" >nul 2>&1
if !errorlevel!==0 (
set /a DELETED+=1
exit /b 0
)
set /a RETRY+=1
if !RETRY! LEQ %MAX_RETRY% (
echo [WAIT] %~nx1 がロック中。%WAIT_SEC% 秒後にリトライ(!RETRY!/%MAX_RETRY%)
timeout /t %WAIT_SEC% /nobreak >nul
goto :del_retry
)
echo [ERROR] %~nx1 の削除失敗(ロック解除できず)
set /a FAILED+=1
exit /b 1
実践例3:アクセス権診断スクリプト
問題発生時の原因調査に使える診断スクリプトです。
@echo off
setlocal
set "TARGET=%~1"
if "%TARGET%"=="" (
echo 使い方: %~nx0 診断対象パス
exit /b 1
)
echo ===== アクセス権診断: %TARGET% =====
:: 1. 管理者権限チェック
net session >nul 2>&1
if errorlevel 1 ( echo [権限] 現在の実行: 一般ユーザー ) else ( echo [権限] 現在の実行: 管理者 )
:: 2. ファイル・フォルダ存在確認
if exist "%TARGET%" ( echo [存在] あり ) else ( echo [存在] なし & exit /b 1 )
:: 3. 属性確認
echo [属性]
attrib "%TARGET%"
:: 4. ACL確認
echo [ACL]
icacls "%TARGET%"
:: 5. 書き込みテスト
echo test > "%TARGET%\__access_test__.tmp" 2>nul
if errorlevel 1 (
echo [書込] NG(書き込み権限がありません)
) else (
del "%TARGET%\__access_test__.tmp" >nul
echo [書込] OK
)
echo ===== 診断完了 =====
13. まとめ:原因別対策早見表
| 原因 | 確認コマンド | 対策 |
|---|---|---|
| 管理者権限の不足 | net session |
管理者として実行・UAC昇格 |
| ACL権限不足 | icacls "パス" |
icacls /grant で権限付与 |
| ファイルロック | tasklist |
taskkill でプロセス終了・リトライ待機 |
| 読み取り専用属性 | attrib "ファイル" |
attrib -r で属性解除 |
| 保護フォルダへの書き込み | 対象パスを確認 | %TEMP% や %APPDATA% を使う |
| ネットワーク権限 | net use |
認証・接続設定を確認 |
| スペース・特殊文字 | パスを確認 | 引用符で囲む・%~1 を使う |
| タスクスケジューラの権限設定 | タスク設定を確認 | /rl highest または SYSTEM ユーザーで実行 |
FAQ
icacls "対象パス" で権限を確認し、必要な権限((F) や (M))が付与されているか確認してください。また、UAC 昇格後にカレントディレクトリが変わっていないかも確認しましょう。attrib で確認)、②他のプロセスがロック中(tasklist で確認)、③権限不足(icacls で確認)のいずれかが原因です。ファイル削除で「アクセスが拒否されました」が出るときの対策も参照してください。\\server\share)を直接使うことも有効です。/R:3 /W:5(3回リトライ・5秒待機)のオプションでリトライ動作を制御できます。ログ出力(/log:out.txt)でスキップしたファイルを記録することもできます。takeown /f "ファイルパス" でファイルの所有権を取得し、icacls "ファイルパス" /grant "%USERNAME%":(F) でフルコントロール権限を付与してから削除します。管理者権限が必要です。
