Windowsのパス長さ制限に関する挙動まとめ

パス長さ制限

Windowsが扱えるパスの長さは260(定数MAX_PATH)に制限され、それ以上の長さのパスをもつファイル・フォルダの操作に支障が出ることがある。

この制限はLongPathsEnabledというレジストリの値を1に設定することで解除できる。例えばPowerShell上で以下を実行すればよい。

Set-ItemProperty "Registry::HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\FileSystem" -Name LongPathsEnabled -value 1

また、現在の値を確認するには以下を実行する。

(Get-Item -Path "Registry::HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\FileSystem").GetValue("LongPathsEnabled")

しかし、制限を解除すれば全ての操作が支障なくできるというわけではない。例えば、Windows APIのマルチバイト文字方式の関数(末尾がAのもの)は長いパスに対応していない(末尾がWのワイド文字方式のものは対応している)らしく、これを使用しているアプリケーションはこの制限を解除しても正しく動かない。またエクスプローラ上での操作性もほとんど改善しない。

これはあくまでWindowsの問題であってファイルシステムの制限ではないので、後述の通りエクスプローラ上でも例えばパス長さ260を超えるファイルを作ること自体は容易である。ネットワーク上のフォルダを閲覧する場合など、実際にWindows上で長さ260を超えるパスを扱う必要がある場面も多く、(制限を解除しなくても)ダブルクリックで開く程度の操作はできることが多い。

以下ではこの問題に関してさらに詳細な挙動を解説する。なお動作確認に使用したのは主にWindows10である。Windows11でも少し試したが、大幅な改善はなさそうである。

関連する公式のドキュメントとしては以下が参考になる。

https://docs.microsoft.com/windows/win32/fileio/naming-a-file?redirectedfrom=MSDN#file-and-directory-names

パスの形式について

今後出てくる様々な挙動を把握するために、ファイルに短い別名を与える仕組みである「8.3形式」およびパス長さ制限の回避に有効な「”\\?\プレフィックス」について紹介する。

8.3形式(短いファイル名)

古いWindowsのファイル名には「8文字以下の名前+ピリオド+3文字以下の拡張子」という長さ制限があった。また、空白を含む一部の記号も使用できない。この制限がなくなった(緩和された)現在でも、Windowsは制限を満たさないファイルに対してこの制限に基づく別名を自動生成する。これが「8.3形式」あるいは「短いファイル名」などと呼ばれるものである。例としては”Program Files”→”PROGRA~1” などがある。8.3形式の名前はコマンドプロンプトのdir /xコマンドで表示できる。

比較的新しいWindowsでは、fsutil 8dot3nameコマンドを使うことで、8.3形式の名前を生成するかどうかをシステム全体およびボリューム(Cドライブ、Dドライブ)ごとに設定できる。デフォルトではCドライブのみ有効になっているようである。

この別名を通常の名前のかわりに使用することで、現実的に多くの場合は長さ制限を回避できるだろう(もちろん階層が深すぎて「短いパス」でも長さ制限を超えてしまう場合などはできない)。また、パスに含まれる空白による問題も回避できる。

後述の通り一部アプリケーションはこれを積極的に使うことで長さ制限を回避しようとすることがある。この際は8.3形式を可能な限り多く使用したパス(可能な限り最も短いパス)が用いられるようである。

例えば8.3形式の名前がCでは有効、Dでは無効(つまりデフォルト設定)だったとする。Dドライブ直下に”longfoldername”という名前で”C:”へのジャンクションを作り、それを経由してC:\Program Filesにアクセスする場合は、”D:\longfoldername\PROGRA~1”が「可能な限りもっとも短いパス」ということになる。

「可能な限り多く」ではなく、短い名前をもつフォルダのうち一部のみを8.3形式としたパスがexplorerのアドレスバーなどで使われているのを見たような気もするが、詳細を記録していなかったため再現できず。

8.3形式は基本的には普通のパスと同じ扱いであるため、多くのアプリケーションが対応しているが、PowerShellなどは強制的に長い名前に変換しようとするため支障が出ることもある(後述)。また、4文字以上の拡張子は3文字に短縮されてしまうため、例えばWordの.docxファイルが.docファイルと混同されるなどの問題が生じる。また他にもシェルの入力補完で表示されないなど、通常のパスと比べて不便であることには変わりない。

\\?\プレフィックス

公式ドキュメントでも用語の定義がはっきりしないのでよくわからないが、パスの先頭に”\\?\”(検索しやすさのために書いておくと、バックスラッシュ(=円記号)2つ+クエスチョンマーク+バックスラッシュ1つ)というプレフィックスを付加すると”Win32 file namespace”というものにアクセスすることになるらしい。具体的にどうなるかというとWindows APIによるパスに対する各種のチェックが行われなくなり、結果として長さ制限を超えるパスを使えるようになる。ただし対応状況はアプリケーションによってまちまちである。

このパスはネットワーク上のファイルを指定するのに使われるUNCパス(UNCはUniversal Naming ConventionあるいはUniform Naming Conventionの略)の一種とも考えられる。UNCパスは「\\コンピュータ名\パス本体」という形式だが、この「コンピュータ名」の部分に?が入っているというわけである。ちなみに、元々UNCパスだったものにこのプレフィックスを付加する場合は\\?\UNC\コンピュータ名\パス本体とすれば良いらしい。

なお、クエスチョンマークの代わりにピリオドを使用した\\.\というプレフィックスもあり、これだと”Win32 file namespace”ではなく”Win32 device namespace”というものにアクセスすることになるらしいが、詳細は不明。長さ制限を回避するには使えないようである。

以降では便宜的に「“\\?\プレフィックス」を指して単に「プレフィックス」と呼ぶ。

ちなみに今回の話題とは無関係だが、connulなどWindows上で許容されない名前のファイルが削除できない際に、コマンドで\\?\\\.\を付けたパスを指定すると削除できる。

Explorerや各シェル、アプリケーションにおける挙動の変化

ここから具体的な挙動の変化を見る。特に記載がないものは、レジストリ値を変更して制限を解除しても変わりがないということである。

以下で「PowerShell」と呼んでいるのはバージョン5であって、6以降(実行ファイル名がpwsh.exeになって以降)では異なるようである。

8.3形式・プレフィックス付きパス等を扱えないアプリケーション

アプリケーションによって細かい挙動は様々だが、プレフィックス付きのものや8.3形式の名前が含まれるパスに関して不具合が出ることがある。はっきりエラーメッセージが出ることもあれば、何も起こらないこともあるし、空白の(ファイルを開いていない状態の)ウインドウが表示される場合もある。いくつか例を挙げておく。

  • Windows Media Playerプレフィックス付きのものや長さ制限を超えるパスを引数に渡すと起動しない(何も起こらず終了する)。
  • ペイント…プレフィックス自体は扱えるが長さ制限を超えるとプレフィックス付きであっても扱えない(引数として渡すと何も起こらず終了する)。
  • Word…プレフィックス付きパスを渡すと、起動はするが新規作成の画面になる。また長さ制限を超えるパス(プレフィックス付き含む)を渡すと「パス名が長すぎる」というようなメッセージを表示した上で新規作成の画面になる。また、”.docx”は拡張子が4文字以上であるため、短いパスとして渡されると不自然な動作になることがある(”.doc”、つまりWord 97-2003文書との混同が生じる)。
  • Visual Studio…8.3形式を用いて短くした.slnや.vcxprojを渡しても、元の(8.3形式を使わない)パスが制限を超えていると「パス名が長すぎる」というようなエラーが表示され開けない。

長さ制限を超えるパスをカレントディレクトリとして実行できないWindowsネイティブアプリケーション(?)

おそらくアプリケーション側の都合で、長さ制限を超えるパスをカレントディレクトリとしての起動に対応していないことがある。具体的には、Git Bashで、長い名前をもつフォルダを開いているとき、mspaintやcmdの実行に失敗する。次のようなメッセージが出る。

Error: Current working directory has a path longer than allowed for a
Win32 working directory.
Can't start native Windows application from here.

bash: /c/Windows/system32/mspaint: File name too long

しかし、同じ状況でgrep.exeの実行は成功する。従ってアプリケーションによって対応状況に差があるものと推測される。ただしこのエラーメッセージはGit Bashによるものであり、またGit Bash以外で違いを確認できていない(例えばcmdやPowerShellではmspaintもgrepシェル側の都合で失敗する)ので、例えばGit Bashが必要以上に多くのプログラムを勝手に”native Windows application”に分類している可能性などは残る。またgrep.exeのようなGit Bash付属の実行ファイル以外で起動できるものは確認していないので、判定条件がよくわからない。

カレントディレクトリを8.3形式によって短くできれば起動できる。

explorer

まず、以下の挙動については全てのフォルダで同様。8.3形式で短くできるものも含まれる。

  • 長さ制限を超えるファイルのリネームができない(元々超えている場合は短くすることもできない)
    • 超えていない場合、制限いっぱいになるとそれ以上入力できなくなる
  • 中にあるファイルのパス長が制限を超えるようにフォルダをリネーム・移動することは可能
    • これにより長さ制限を超えるパスをもつファイル・フォルダをエクスプローラ上で容易に作れる。逆に、長すぎてリネームできないファイルなども、外側のフォルダをいったん短い名前に変える・短い名前の場所に移動することで操作できるようになる
  • 長さ制限を超えてもフォルダを開くことは可能。

さて、explorerは、制限を超える長いパスに対しては概ね次のような原則で対処しようとするようである。

  1. 8.3形式の名前を使用して「可能な限り最も短いパス」を得て、これを使う。
  2. 8.3形式の名前がない、あるいはそれを使っても制限を超過するなどの場合は、パス先頭に”\\?\プレフィックスを付加する。

例えばexplorerのアドレスバーを見ると、このように動作していることがわかるだろう。あるいは、そのフォルダおけるexplorerの挙動はアドレスバーを見れば大体予測できるということにもなる。ファイルに関して調べたければ「パスのコピー」を使うとよい。なお、手動でプレフィックスや8.3形式の名前をエクスプローラのアドレスバーに入力して移動した際は、通常のパスに変換される(それが長さ制限を超えていれば改めて上記の対処が行われる)。

1のとき

ダブルクリックでファイルを開くことができるほか、右クリックメニューの「送る」「Codeで開く」(※VS Codeを適切な設定でインストールすると表示される)なども正常動作する。なお「PowerShell ウインドウをここで開く」は、動作するが、PowerShellは強制的に通常の(長い)名前を使おうとするため、カレントディレクトリとしては通常の名前が表示される(この先の挙動はPowerShellの項目を参照)。また、PowerShellを使用するよう設定したWindows Terminalをここで開くと、制限を解除した場合は通常形式のパスをカレントディレクトリとして正しく起動するが、解除しない場合はカレントディレクトリをC:\WINDOWS\System32\WindowsPowerShell\v1.0として起動する。

ファイルの新規作成は可能だが、フォルダを作成しようとするとエラーが出る。ファイルやフォルダを「ごみ箱に移動」できる。

2のとき

2に当てはまるフォルダでは、「Codeで開く」など外部プログラムを起動するような右クリックメニューの多くが動作しない(Explorer.EXEによる”ディレクトリ名が無効です。”とのダイアログが出る)。「開く」も動作せずファイルをダブルクリックで開くこともできない(例えば.txtがメモ帳に関連付けられた状態で開いてみるとよい)(※これに関してはWindows11で修正された模様)。ただしCOMを用いて実装されているメニュー(レジストリコマンドラインではなくUUIDが書かれているようなもの)は正常に動作するようである(例えば「映画 & テレビ」「フォト」のようないわゆる「アプリ」で開く場合)。

以下はCOMが用いられているか不明(未調査)だがその可能性が考えられる。

  • PowerShell ウインドウをここで開く」…正常に動作する。
  • 「プログラムから開く」…「開く」とは異なり、(アプリケーション側が対応していれば)正常に動作する。
  • 「送る」…Explorer.EXEのエラーは表示されない。ただし、特殊な方法(これもCOM?)で実装されている「ドキュメント」「デスクトップ (ショートカットを作成)」「圧縮 (zip 形式) フォルダー」メニューなどを除けば、選択しても何も起こらない。また、zipのメニューに関しても、最終的にzip作成には失敗する。なお、この「送る」に関しては、(2に当てはまるフォルダ内でなくとも)2に当てはまるファイルが一つでも含まれていると同様に動かないようである。

また、「新規作成」メニューにはフォルダの作成のみ表示されるが、なぜか”管理者マーク”が付いており、押しても何も起こらない。従ってファイルもフォルダも作れない。「ごみ箱に移動」は動作せず、delキーを押しただけで「完全に削除しますか?」と聞かれる(完全に削除することは可能)。

コマンドプロンプト

制限を解除した場合に限り長いパスを扱える(cdやdirが動作する)。また8.3形式の名前も普通に使える。

プレフィックスは、全く解釈できないわけではない(例えばrdコマンドの引数に使うことはできる)が、カレントディレクトリとしては許容されないようで、指定してcdしようとすると「CMD では UNC パスは現在のディレクトリとしてサポートされません。」と言われる。

外部プログラムを実行する際は、(制限が解除されていても)カレントディレクトリのパスが長いと判定したら「可能な限り最も短いパス」を代わりに使うようで、(それで制限以下の長さにできるフォルダであれば)正しく起動できる。

PowerShell

制限を解除した場合に限り長いパスを扱える点はcmdと同じである。しかし前述の通り、カレントディレクトリに8.3形式が使われるのを許容しないようで、強制的に長い名前に変換するため、しばしば奇妙な挙動を引き起こす。

例えば、カレントディレクトリのパスが200文字だったとして、そこに名前が100文字のフォルダがあったとする。いずれも実体はCドライブにあって8.3形式の名前が有効とする。このとき、パス長さ制限が解除されていなくても、8.3形式の名前を使えばcd自体はできる。しかしcdが成功すると同時にカレントディレクトリは長い名前に変換されるため、カレントディレクトリは300文字程度になり制限を超えてしまい、そこでのdirコマンドなどの実行は失敗するようになってしまう。

また、長さ制限を超えるパスがカレントディレクトリであるときに外部プログラムを実行すると、制限が解除されていない場合は「可能な限り最も短いパス」を使おうとするが、解除されている場合は長いパスをそのまま使おうとする(cmdとの違い)。結果として実行に失敗する。つまり、制限を解除した結果としてむしろ実行が失敗するようになるという状況が発生している。

プレフィックスには対応していて基本的な操作ができる。カレントディレクトリに設定するとMicrosoft.PowerShell.Core\FileSystem::\\?\C:\Usersのように表示される。

またカレントディレクトリがプレフィックス付きであるときに外部プログラムを実行するときは、不要な\\?\\\.\を除去してくれるようで、正しく起動できる。これは\\?\C:\Windowsのようなフォルダで正しく起動できるということであって、そもそも\\?\を付けないと扱えないような長いパスでの実行はいずれにしても失敗する。

また、(制限を解除していない状態だとしても)この際に「最も短いパス」を使用することまではしてくれないようで、Cドライブ上の長いパスに\\?\を付けたものをカレントディレクトリとしてnotepadを実行してみたが失敗した。

また、なぜかCドライブ直下を対象にしたcd \\?\C:cd \\.\C:はうまくいかない(cd \\?\C:\Userscd \\.\C:\Usersは成功する)。\\.\に関しては一旦cd \\.\C:\Usersなどしてからcd ..をするとCドライブにいけるがこのときはなぜか\\.\が消えてMicrosoft.PowerShell.Core\FileSystem::C:という表示になる。\\?\の場合はこれもできない。

Git Bash

git bashUnix由来のシェルであるためか、それ自体で長さ制限を超えるパスを扱う能力を持っているようである。従って制限を解除しなくても長いパスを扱える。また8.3形式の名前も使える。

「可能な限り最も短いパス」を得ようとするような動作はしないため、長いパスをもつカレントディレクトリでの外部プログラム実行は失敗する(前述の通り、Git Bash内蔵のgrep.exeなどは例外)。

Git Bashでは、\\?\\\.\//./は使うとエラーになり、//?/を付けた場合はcdには成功するが//?/が除去される。

結論

こうしてみると長さ制限を解除しても大した改善はないというのが実情である。