web-dev-qa-db-ja.com

Windowsにはなぜ260文字のパス長制限があるのですか?

私はこの問題に何度か気付かずに思い付きました。

  • ディープパスでオープンソースのJavaプロジェクトに取り組もうとしている
  • 深いFitnesseウィキツリーをソース管理に保存する
  • ソース管理ツリーをインポートするためにBazaarを使用しようとしているエラー

この制限が存在するのはなぜですか?

まだ削除されていないのはなぜですか。

パス制限にどう対処しますか? ...そしていいえ、LinuxやMac OS Xに切り替えることは、この質問に対する有効な答えではありません。

363
Jeffrey Cameron

この記事を引用すること https://docs.Microsoft.com/ja-jp/windows/desktop/FileIO/naming-a-file#maximum-path-length-limitation

最大パス長制限

Windows API(以下の段落で説明するいくつかの例外はあります)では、パスの最大長はMAX_PATHで、260文字として定義されています。ローカルパスは、ドライブ文字、コロン、バックスラッシュ、バックスラッシュで区切られた名前の構成要素、および末尾のヌル文字の順序で構造化されています。たとえば、ドライブDの最大パスは "D:\"です。256文字のパス文字列<NUL> "where" <NUL> "は、現在のシステムコードページの見えない終端のヌル文字を表します(文字<>は、見やすくするためにここで使用されており、有効なパス文字列の一部にはできません)

1 + 2 + 256 + 1か[drive] [:\] [path] [null] = 260であることがわかります。256はDOS時代からの妥当な固定文字列長であると考えることができます。そしてDOS APIに戻ると、システムはドライブごとに現在のパスを追跡していることがわかり、最大ドライブ数は 26(記号付きの32)になります (そして現在のディレクトリ).

INT 0x21 AH = 0x47は、「この関数はドライブ文字と最初のバックスラッシュなしでパスの説明を返す」と言っています。システムはCWDをペア(ドライブ、パス)として格納しているので、 drive(1 = A、2 = B、…)。0を指定すると、ドライブのパスはINT 0x21 AH = 0x15 AL = 0x19で返されると想定します。これで、なぜ4バイトがパス文字列に格納されていないのですか。

640Kで十分なRAMなので、なぜ256バイトのパス文字列です。

211
valli

NTFSファイルシステムは32k文字までのパスをサポートしているので、これは厳密には正しくありません。 win32 apiと "\\?\"を使用して、260文字を超えるパスを使用できます。

.Net BCLチームブログ からの長いパスの詳細な説明。
短い抜粋は、長い道のりの問題を強調しています

もう1つの懸念は、長いパスのサポートを公開することによって生じる可能性のある動作の矛盾です。 \\?\接頭辞を持つ長いパスは、ほとんどのファイル関連のWindows APIで使用できますが、すべてのWindows APIでは使用できません。たとえば、モジュールを呼び出しプロセスのアドレスにマップするLoadLibraryは、ファイル名がMAX_PATHより長いと失敗します。つまり、MoveFileを使用すると、DLLをパスが260文字を超えるような場所に移動できるようになりますが、DLLをロードしようとすると失敗します。 Windows API全体に同様の例があります。いくつかの回避策がありますが、それらはケースバイケースです。

142
softveda

問題は、なぜ制限がまだ存在するのかということです。確かに現代のWindowsはより長いパスを許可するためにMAX_PATHの側面を増やすことができます。制限が取り除かれなかったのはなぜですか?

  • 削除できない理由は、Windowsが変更されることはないと約束していたためです。

API契約を通じて、Windowsはすべてのアプリケーションに対して、標準ファイルAPIが260文字より長いパスを決して返さないことを保証しています。

次の正しいコードを考えてください。

WIN32_FIND_DATA findData;

FindFileFirst("C:\Contoso\*", ref findData);

Windowsはそれが私のWIN32_FIND_DATA構造を生成することを私のプログラムに保証しました

WIN32_FIND_DATA {
   DWORD    dwFileAttributes;
   FILETIME ftCreationTime;
   FILETIME ftLastAccessTime;
   FILETIME ftLastWriteTime;
   //...
   TCHAR    cFileName[MAX_PATH];
   //..
}

私のアプリケーションは定数MAX_PATHの値を宣言しませんでした、Windows APIは宣言しました。私のアプリケーションはその定義された値を使用しました。

私の構造は正しく定義されており、592バイトの合計を割り当てるだけです。つまり、私は260文字より少ないファイル名しか受け取れないということです。 Windowsは、私が自分のアプリケーションを正しく書いたならば、私のアプリケーションは今後も動作し続けると約束しました

Windowsが260文字より長いファイル名を許可するのであれば、私の既存のアプリケーション(正しいAPIを正しく使用していた)は失敗するでしょう。

MicrosoftにMAX_PATH定数の変更を求める人は、まず既存のアプリケーションが失敗しないようにする必要があります。たとえば、私はまだWindows 3.11上で動作するように書かれたWindowsアプリケーションを所有し使用しています。それはまだ64ビットWindows 10で動作します。それは後方互換性があなたを得るものです。

Microsoftは、32,768のフルパス名を使用する方法を作成しました。しかし彼らはそれをするために新しいAPI契約を作成しなければなりませんでした。たとえば、シェルAPIを使用してファイルを列挙する必要があります(すべてのファイルがハードドライブまたはネットワーク共有に存在するわけではないため)。

しかし、既存のユーザーアプリケーションを壊さないようにする必要もあります。大多数のアプリケーションはファイル作業にシェルAPIを使用しませんしません。誰もがFindFirstFile/FindNextFileを呼び出し、それを毎日呼び出します。

99
Ian Boyd

Windows 10から/あなたは 制限を取り除くことができます レジストリキーを修正することによって。

ヒントWindows 10バージョン1607以降、MAX_PATHの制限が一般的なWin32ファイルおよびディレクトリ機能から削除されました。ただし、新しい動作を選択する必要があります。

レジストリキーを使用すると、新しいロングパス動作を有効または無効にできます。ロングパス動作を有効にするには、レジストリキーをHKLM\SYSTEM\CurrentControlSet\Control\FileSystem LongPathsEnabledに設定します(Type:REG_DWORD)。影響を受けるWin32ファイルまたはディレクトリ関数への最初の呼び出しの後、キーの値はシステムによって(プロセスごとに)キャッシュされます(リストは続きます)。レジストリキーは、プロセスの有効期間中に再読み込みされません。システム上のすべてのアプリがキーの値を認識するためには、キーが設定される前に一部のプロセスが開始されている可能性があるため、再起動が必要になる場合があります。レジストリキーはComputer Configuration > Administrative Templates > System > Filesystem > Enable NTFS long pathsのグループポリシーでも制御できます。マニフェストを使用して、アプリごとに新しいロングパス動作を有効にすることもできます。

<application xmlns="urn:schemas-Microsoft-com:asm.v3">
    <windowsSettings xmlns:ws2="http://schemas.Microsoft.com/SMI/2016/WindowsSettings">
        <ws2:longPathAware>true</ws2:longPathAware>
    </windowsSettings>
</application>
53
Root Loop

フォルダをドライブとしてマウントすることができます。コマンドラインから、パスC:\path\to\long\folderを持っているなら、あなたはそれをドライブ文字X:にマッピングすることができます:

subst x: \path\to\long\folder
29
jonchang

パス制限に対処する1つの方法は、シンボリックリンクを使用してパスエントリを短くすることです。

例えば:

  1. 長いパスへの短いリンクを保持するためにC:\pディレクトリを作成する
  2. mklink /J C:\p\foo C:\Some\Crazy\Long\Path\foo
  3. 長いパスの代わりにC:\p\fooをあなたのパスに追加してください
16
JDiMatteo

Windowsでのパスサイズ制限に対処する方法について - 7Zip を使用してパス長に敏感なファイルをパックする(そしてアンパックする)ことは実行可能な回避策のようです。私はこれを使っていくつかのIDEインストール(Eclipseプラグインのパス、いいね!)と自動生成された文書を積み重ねてきましたが、今のところ単一の問題はありませんでした。

それがどのようにしてWindowsによって設定された260文字の制限を(技術的なPoVから)回避するかはよくわからないが、それはうまくいく!

彼らのSourceForgeのページでのさらなる詳細 here

「NTFSは実際には最大32,000文字のパス名をサポートできます。」

7-Zipもそのような長い名前をサポートします。

しかし、それはSFXコードでは無効になっています。長い道のりが気に入らないユーザーもいます。それが私がSFXコードでそれを無効にした理由です。

リリースノート

9.32アルファ2013-12-01

  • 260文字を超えるファイルパス名のサポートが改善されました。

4.44 beta 2007-01-20

  • 7-Zipは現在260文字より長いファイルパス名をサポートします。

重要な注意:これが正しく動作するためには、 7Zip "Extract"に宛先パスを指定する必要があります。目的のフォルダにファイルをドラッグ&ドロップするのではなく、直接ダイアログを表示します。それ以外の場合は、 "Temp"フォルダが一時キャッシュとして使用され、Windowsエクスプローラがファイルを "最終的な休憩場所"に移動し始めると、同じ260文字の制限に戻ります。詳細については this question への回答を参照してください。

7
Priidu Neemre

なぜこれがまだ存在するのか - MSはそれを優先事項とは見なさず、(少なくともこの例では)OSの進歩よりも後方互換性を重視しています。

私が使用する回避策はそれらの標準的な、人間が読めるバージョンの代わりに、パス内のディレクトリに "短い名前"を使用することです。だから例えばC:\Program Files\のための私はC:\PROGRA~1\を使うだろうあなたはdir /xを使って同等の短い名前を見つけることができます。

7
Conrad

PowerShellを使用して長いパス名を有効にできます。

Set-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\FileSystem' -Name LongPathsEnabled -Type DWord -Value 1 

別のバージョンでは、Computer Configuration/Administrative Templates/System/Filesystemでグループポリシーを使用します。

Group Policy Editor

6
MovGP0

それはし、それは何らかの理由でデフォルトですが、このレジストリキーで簡単に上書きすることができます。

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\FileSystem]
"LongPathsEnabled"=dword:00000001

参照してください: https://blogs.msdn.Microsoft.com/jeremykuhne/2016/07/30/net-4-6-2-and-long-paths-on-windows-10 /

4

それに対処するもう1つの方法は、ファイルに対して何をしたいのかに応じて、Cygwinを使用することです(つまり、Cygwinコマンドがニーズに合っている場合)。

たとえば、Windowsエクスプローラでさえできないファイルのコピー、移動、または名前変更が可能です。あるいはもちろん、md5sum、grep、gzipなどのようなそれらのコンテンツも扱ってください。

あなたがコーディングしているプログラムについても、それらをCygwin DLLにリンクすることができ、それによってそれらが長いパスを使うことを可能にするでしょう(私はこれをテストしていません)。

2
eliblanco87