Windowsのパス長制限(MAX_PATH=260文字)は、レジストリで「長いパスを有効化」したり\\?\ プレフィックスを使えば大半は解決できます。しかし「レジストリ変更が組織ポリシーで禁止されている」「対象コマンドが \\?\ に非対応」「ロックと長パスが重なって手が出ない」といった状況では、標準手段だけでは突破できません。本記事では、そうした「それでもダメなとき」に使える実践的な最終手段を体系的に解説します。
\\?\ プレフィックス・subst・robocopy の基本)についてはWindowsのパス長制限(MAX_PATH=260)完全攻略を参照してください。本記事はその先のケースを扱います。
コマンド別の長パス対応状況
最終手段を選ぶ前に、使おうとしているコマンドが長パスに対応しているかを確認します。
| コマンド | \\?\ 対応 | 260文字超え | 備考 |
|---|---|---|---|
robocopy |
○ | ○ | 長パスの筆頭手段。/256 フラグ(Win10以降) |
xcopy |
△ | △ | 環境によって動作が不安定 |
copy |
× | × | 260文字制限を超えると失敗 |
del |
○ | ○ | \\?\ 付きなら長パス可 |
rd /s /q |
△ | × | 深いツリーで失敗しやすい |
dir |
○ | ○ | \\?\ 付きで列挙可能 |
move |
× | × | 長パスは基本的に失敗 |
powershell (Remove-Item等) |
○ | ○ | -LiteralPath と \\?\ で対応 |
tar(Win10以降内蔵) |
○ | ○ | 長パスを含むアーカイブに対応 |
最終手段①:SUBST で仮想ドライブに割り当てる
長いパスの途中までを仮想ドライブに割り当て、残りのパスを短くします。ポリシー変更不要で副作用が少なく、まず試す価値があります。
@echo off
rem C:\very\long\path\to\project を X: に割り当て
subst X: "C:\very\long\path\to\project"
if errorlevel 1 (
echo SUBST 失敗: ドライブ文字が使用中の可能性があります
exit /b 1
)
rem 以降は X:\ 以下の短いパスで操作
dir X:\src
robocopy "X:\src" "D:\backup\src" /E
rem 処理後は必ず解除
subst X: /d
subst ではなくmklink /D(シンボリックリンク)か mklink /J(ジャンクション)を使います。SUBST は再起動すると消えます。また昇格プロセスとの共有には制限があります。
@echo off
setlocal EnableDelayedExpansion
set "SRC=C:\very\long\path\to\project"
rem 未使用のドライブレターを探す(Z:から順番に)
set "DRV="
for %%L in (Z Y X W V U T S) do (
if "!DRV!"=="" (
subst %%L: "!SRC!" >nul 2>&1
if not errorlevel 1 set "DRV=%%L"
)
)
if "!DRV!"=="" (
echo 使用可能なドライブが見つかりません
exit /b 1
)
echo !DRV!: を使用中
rem === ここで !DRV!:\ を使って処理 ===
dir "!DRV!:\"
subst "!DRV!:" /d
endlocal
最終手段②:mklink でジャンクション・シンボリックリンクを使う
SUBST は再起動すると消えますが、mklink /J(ジャンクション)は永続します。深い階層の途中に短い名前のジャンクションを作り、有効なパス長を短縮します。
@echo off net session >nul 2>&1 || goto :no_admin rem 深い階層の途中に短いジャンクションを作る rem C:\proj\deep\nested\module を C:\m にリンク mklink /J "C:\m" "C:\proj\deep\nested\module" rem 以降は C:\m\src\... という短いパスで操作 dir "C:\m\src" rem 作業後はリンクを削除(/J はリンクだけ消え、実体は残る) rmdir "C:\m" goto :eof :no_admin echo 管理者権限が必要です(mklink /J はディレクトリジャンクション作成に必要) exit /b 1
| 種類 | コマンド | 対象 | 管理者権限 | 再起動後 |
|---|---|---|---|---|
| ジャンクション | mklink /J |
ローカルディレクトリ | 必要 | 維持 |
| シンボリックリンク(ディレクトリ) | mklink /D |
ローカル・ネットワーク | 必要 | 維持 |
| シンボリックリンク(ファイル) | mklink |
ファイル | 必要 | 維持 |
| 仮想ドライブ | subst |
ローカルディレクトリ | 不要 | 消える |
最終手段③:robocopy /MIR で深いツリーを削除する
rd /s /q が深いツリーで失敗するとき、空フォルダを用意して robocopy /MIR(ミラーリング)すると対象フォルダが空になります。その後に rd で削除します。
@echo off
setlocal
set "TARGET=C:\very\long\deep\tree"
set "EMPTY=%TEMP%\empty_%RANDOM%"
mkdir "%EMPTY%"
rem 空フォルダを対象にミラーリング → 中身がすべて消える
robocopy "%EMPTY%" "%TARGET%" /MIR /R:1 /W:1 /NFL /NDL /NJH /NJS /NP >nul
rem 空になったフォルダを削除
rd /s /q "%TARGET%" 2>nul
rd "%EMPTY%" 2>nul
if exist "%TARGET%" (
echo 削除失敗: まだ残っています
exit /b 1
)
echo 削除完了
endlocal
exit /b 0
robocopy は /256 フラグ(Windows 10 1607以降)で MAX_PATH を超えるパスも扱えます。
@echo off rem /256: 長いパスを有効にして処理 robocopy "C:\very\long\path\source" "D:\backup\dest" /E /256 /R:1 /W:1 /NFL /NP
最終手段④:PowerShell -LiteralPath で操作する
cmd の制限を受けずに PowerShell の .NET API を使うことで、長パスのファイル操作が確実になります。-LiteralPath を使うとワイルドカードや特殊文字の展開を抑止できます。
@echo off
set "P=\\?\C:\very\long\日本語\path\file.txt"
rem 読み込み
powershell -NoProfile -Command ^
"Get-Content -LiteralPath '%P%' -Encoding UTF8 | Out-File -FilePath 'C:\work\out.txt' -Encoding UTF8"
rem 削除(再帰的)
powershell -NoProfile -Command ^
"Remove-Item -LiteralPath '%P%' -Force -Recurse"
rem コピー
powershell -NoProfile -Command ^
"Copy-Item -LiteralPath '%P%' -Destination 'C:\work\file.txt' -Force"
@echo off
rem 260文字を超えるパスを列挙
powershell -NoProfile -Command ^
"Get-ChildItem -LiteralPath 'C:\deep\path' -Recurse |" ^
"Where-Object { $_.FullName.Length -gt 260 } |" ^
"Select-Object FullName"
最終手段⑤:8.3形式の短縮名を使う
NTFSボリュームで 8.3 形式の短縮名が有効になっていれば、長いフォルダ名を短縮名で置き換えることでパス長を削減できます。組織ポリシーで無効化されている場合は使えないため、事前に確認が必要です。
@echo off rem dir /x で短縮名を確認 dir /x "C:\very" rem 例)LongFo~1 のような短縮名が表示される rem 短縮名を使って操作(全角文字の長いフォルダ名を回避) copy "C:\VeryLo~1\SubDir~1\file.txt" "C:\work\file.txt" rem 有効かどうかの確認 fsutil 8dot3name query C:\
8dot3name creation is disabled と表示)な場合は、管理者権限で fsutil 8dot3name set C: 0 を実行すると有効化できます。ただし大量ファイルがある場合は fsutil での有効化後に fsutil 8dot3name scan C:\ /v で既存ファイルの短縮名を生成する必要があります。
最終手段⑥:WSL(Windows Subsystem for Linux)を使う
WSL が使える環境では Linux のファイル操作コマンドでWindowsのパス制限を回避できます。特にシンボリックリンクの多いプロジェクトや、深いネスト構造の一括削除に有効です。
@echo off rem Windowsのパスを /mnt/c/ 形式に変換してWSLで操作 wsl rm -rf "/mnt/c/very/long/deep/nested/folder" rem WSL で長パスのファイルをコピー wsl cp "/mnt/c/very/long/path/file.txt" "/mnt/c/work/file.txt" rem WSL で 260文字超えのファイルを一覧 wsl find "/mnt/c/deep/path" -name "*.log" -type f
wsl cp でコピーすると破損する可能性があります。テキスト処理は問題ありませんが、実行ファイルや設定ファイルの扱いは慎重に行ってください。
最終手段⑦:浅い一時ディレクトリで処理してから戻す
深い階層での直接作業をあきらめ、浅い一時ディレクトリに移してから処理する方法です。ビルド・圧縮・変換など、入出力のパス長制限がある処理で特に有効です。
@echo off setlocal set "SRC=C:\very\long\deep\project\src" set "WRK=C:\wrk\tmp_%RANDOM%" rem 作業ディレクトリを作成 mkdir "%WRK%" 2>nul rem 処理対象を浅い場所にコピー robocopy "%SRC%" "%WRK%\src" /E /256 /R:1 /W:1 /NFL /NP >nul rem 短いパスで処理(例:ビルドや圧縮) pushd "%WRK%" tar -cf "C:\output\result.tar" src popd rem 後片付け robocopy "%TEMP%\empty_ref" "%WRK%" /MIR /R:1 /W:1 /NP >nul 2>&1 rd /s /q "%WRK%" 2>nul endlocal echo 完了: C:\output\result.tar
ロックと長パスが重なった場合の複合対処
プロセスがロック中かつ長パスで削除できない、という最も厄介なケースへの対処手順です。
@echo off
setlocal
set "T=\\?\C:\very\long\locked\folder"
rem 1) ロック元プロセスを停止
taskkill /f /im Problem.exe >nul 2>&1
sc stop ProblemService >nul 2>&1
timeout /t 3 >nul
rem 2) PowerShell で長パスをまず削除試行
powershell -NoProfile -Command ^
"Remove-Item -LiteralPath '%T%' -Force -Recurse -ErrorAction SilentlyContinue"
rem 3) まだ残っていれば robocopy /MIR で空にする
if exist "%T%\" (
set "EMPTY=%TEMP%\empty_%RANDOM%"
mkdir "!EMPTY!"
robocopy "!EMPTY!" "%T%" /MIR /R:1 /W:1 /NFL /NDL /NJH /NJS /NP >nul
rd /s /q "%T%" 2>nul
rd "!EMPTY!" 2>nul
)
rem 4) それでも残るなら次回起動時に削除をスケジュール
if exist "%T%\" (
echo まだ削除できません。再起動後に削除を試みます...
rem PendingFileRenameOperations は高度な操作のため、ここでは手動対応を推奨
)
endlocal
CI/CD環境でのパス長対策
GitHub Actions・Azure DevOps・Jenkins などのCI/CD環境では、デフォルトのワークスペースが深い階層に作られることがあります。
rem GitHub Actions の場合: env.GITHUB_WORKSPACE で確認 rem 対処法1: チェックアウトパスを浅くする rem actions/checkout の with.path を "w" などに設定 rem 対処法2: バッチ内で subst を使う subst W: "%GITHUB_WORKSPACE%" >nul 2>&1 cd /d W:\ rem 対処法3: レジストリで長いパスを有効化(管理者権限が必要) reg add "HKLM\SYSTEM\CurrentControlSet\Control\FileSystem" /v LongPathsEnabled /t REG_DWORD /d 1 /f
最終手段の使い分けフロー
| 状況 | 推奨する最終手段 |
|---|---|
| レジストリ変更不可・一時的な作業 | SUBST で仮想ドライブ化 |
| 恒久的に短いパスが必要 | mklink /J でジャンクション作成 |
| 深いツリーを丸ごと削除したい | robocopy /MIR(空フォルダ同期) |
| 特殊文字・日本語を含むパスの操作 | PowerShell -LiteralPath |
| 短縮名が有効な環境 | dir /x で 8.3 短縮名を取得して利用 |
| WSLが使える環境 | wsl コマンドで Linux 側から操作 |
| 処理対象の階層が深すぎる | 浅い一時ディレクトリにコピーして処理 |
| ロック + 長パスの複合問題 | プロセス停止 → PowerShell → robocopy /MIR の順 |
よくある質問
subst は現在のログオンセッション限りです。再起動後も維持したい場合は mklink /J でジャンクションを作成するか、スタートアップに subst コマンドを登録してください(タスクスケジューラでログオン時に実行)。taskkill や sc stop でロック元を止めてから実行してください。C:\src\ や C:\a\w\ のような浅いパスをプロジェクトルートにすることが根本解です。PsExec で SYSTEM 権限で実行する、または WinPE 環境(Windowsインストールメディアのコマンドプロンプト)から操作する方法もあります。まとめ
通常手段でパス長制限を突破できないときの手段を整理します。
- まず
substで仮想ドライブ化して路長を縮める(再起動で消えてよい場合) - 永続化が必要なら
mklink /Jでジャンクションを作成する - 深いツリーの削除は
robocopy /MIR(空フォルダと同期)が確実 del/copy/moveが失敗するときは PowerShell の-LiteralPathに切り替える- WSL が使える環境では Linux 側のコマンドで操作する
- 根本解は作業ルートを
C:\src\などの浅いパスに固定すること

