私は不都合な瞬間にこの問題に数回直面しています:
- 深いパスを持つオープンソースのJavaプロジェクトで作業しようとしています
- ソース管理にDeep Fitnesse Wikiツリーを格納する
- Bazaarを使用してソース管理ツリーをインポートしようとするとエラーが発生する
なぜこの制限が存在するのですか?
なぜまだ削除されていないのですか?
パスの制限にどのように対処しますか?いいえ、LinuxまたはMac OS Xに切り替えることは、この質問に対する有効な回答ではありません;)
私は不都合な瞬間にこの問題に数回直面しています:
なぜこの制限が存在するのですか?
なぜまだ削除されていないのですか?
パスの制限にどのように対処しますか?いいえ、LinuxまたはMac OS Xに切り替えることは、この質問に対する有効な回答ではありません;)
回答:
この記事を引用https://docs.microsoft.com/en-us/windows/desktop/FileIO/naming-a-file#maximum-path-length-limitation
最大パス長の制限
Windows APIでは(次の段落で説明するいくつかの例外はあります)、パスの最大長はMAX_PATHで、260文字として定義されています。ローカルパスは、ドライブ文字、コロン、バックスラッシュ、バックスラッシュで区切られた名前コンポーネント、終端のnull文字の順に構成されています。たとえば、ドライブDの最大パスは "D:\ 256文字のパス文字列 <NUL>"です。 "<NUL>"は、現在のシステムコードページの非表示の終了NULL文字を表します。(文字<>はここでは視覚的にわかりやすくするために使用されており、有効なパス文字列の一部にすることはできません。)
これで、1 + 2 + 256 + 1または[ドライブ] [:\] [パス] [null] = 260であることがわかります。256は、DOS日からの妥当な固定文字列長であると想定できます。DOS APIに戻ると、システムがドライブごとの現在のパスを追跡していることがわかり、26(シンボルを含む32)の最大ドライブ(および現在のディレクトリ)があります。
INT 0x21 AH = 0x47は、「この関数はドライブ文字と最初のバックスラッシュなしでパスの説明を返します。」したがって、システムはCWDをペア(ドライブ、パス)として保存し、ドライブ(1 = A、2 = B、…)を指定してパスを要求することがわかります。0を指定すると、 INT 0x21 AH = 0x15 AL = 0x19によって返されるドライブ。これで、4バイトがパス文字列に格納されないため、なぜ256ではなく260であるかがわかります。
640Kで十分なRAMがあるのに、なぜ256バイトのパス文字列か。
NTFSファイルシステムは32k文字までのパスをサポートするため、これは厳密には当てはまりません。win32 api \\?\
を使用し、パスに" "を付けると、260文字を超える文字を使用できます。
.Net BCLチームのブログからの長い道のりの詳細な説明。
小さな抜粋は、長いパスの問題を強調しています
もう1つの懸念は、長いパスのサポートを公開することによって生じる一貫性のない動作です。
\\?\
接頭辞付きの長いパスは、ほとんどのファイル関連のWindows APIで使用できますが、すべてのWindows APIでは使用できません。たとえば、ファイル名がMAX_PATHより長い場合、モジュールを呼び出しプロセスのアドレスにマップするLoadLibraryは失敗します。つまり、MoveFileを使用すると、DLLをそのパスが260文字を超えるような場所に移動できますが、DLLをロードしようとすると失敗します。Windows API全体に同様の例があります。いくつかの回避策がありますが、それらはケースバイケースです。
問題はなぜ制限がまだ存在するのかということです。確かに最新のWindowsではMAX_PATH
、より長いパスを許可するようにサイドを増やすことができます。制限が解除されていないのはなぜですか?
Windowsは、APIコントラクトを通じて、標準のファイルAPIが260
文字よりも長いパスを返さないことをすべてのアプリケーションに保証しています。
次の正しいコードを検討してください。
WIN32_FIND_DATA findData;
FindFirstFile("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
を呼び出すだけで、1日にそれを呼び出します。
Windows 10から、レジストリキーを変更することで制限を取り除くことができます。
ヒント Windows 10バージョン1607以降、一般的なWin32ファイルおよびディレクトリ関数からMAX_PATHの制限がなくなりました。ただし、新しい動作にオプトインする必要があります。
レジストリキーを使用すると、新しいロングパス動作を有効または無効にできます。長いパスの動作を有効にするには、レジストリキーを
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>
フォルダをドライブとしてマウントできます。コマンドラインから、パスがある場合は、次を使用してパスC:\path\to\long\folder
をドライブ文字にマッピングできますX:
。
subst x: \path\to\long\folder
subst
ローカルセッション/アカウントです- 「システム全体」にする方法については、superuser.com /
パス制限に対処する1つの方法は、シンボリックリンクを使用してパスエントリを短くすることです。
例えば:
C:\p
長いパスへの短いリンクを保持するディレクトリを作成するmklink /J C:\p\foo C:\Some\Crazy\Long\Path\foo
C:\p\foo
長いパスの代わりにパスに追加する/j
オプションは、ローカルボリュームデバイスまたはローカルボリューム上のパス(Unixバインドマウントなど)のジャンクションマウントポイントを作成します。シンボリックリンクは作成しません。ジャンクションマウントポイントは常にサーバーで評価され、ローカルデバイスをターゲットにする必要があるため、これは重要な違いです。シンボリックリンクはクライアントで評価され、リモートパスをターゲットにする場合があります(ポリシーで許可されている場合)。subst.exeドライブ(つまりDefineDosDeviceW
)と同様に、ジャンクションターゲットは通常、約4K文字に制限されています。実際には8K文字で、代替パスと表示パスの間でほぼ均等に分割されます。
PowerShellを使用して長いパス名を有効にできます。
Set-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\FileSystem' -Name LongPathsEnabled -Type DWord -Value 1
別のバージョンは、Computer Configuration
/ Administrative Templates
/ System
/ でグループポリシーを使用することFilesystem
です:
なぜこれがまだ存在する- MSは、優先順位を検討していない、と(少なくともこの例では)彼らのOSを進め超える値の下位互換性。
私が使用する回避策は、標準の人間が読めるバージョンではなく、パス内のディレクトリに「短い名前」を使用することです。したがって、たとえば、C:\Program Files\
私は次のように使用しC:\PROGRA~1\
ますdir /x
。
PATH
してに渡しSearchPathW
ます。とにかく、ランタイムライブラリはNTの「\\?\」デバイスパスを作成するため、これも効率的です。新しいファイルシステムについては、セキュリティがないため、ポータブルアプリケーション以外のソフトウェアがexFATボリュームにインストールされていることはおそらくありませんが、ReFSを除外しません。ユーザーは、利便性、スペース、またはパフォーマンスの理由から、プログラムを標準以外の場所にインストールします。
Windowsでのパスサイズの制限に対処する方法については、7zipを使用してパス長の機密ファイルをパック(およびアンパック)することは、実行可能な回避策のようです。私はこれを使用して、いくつかのIDEインストール(Eclipseプラグインパス、そうですね!)と自動生成されたドキュメントの山を転送しましたが、今のところ1つの問題は発生していません。
Windowsによって設定された260文字の制限(技術的なPoVから)をどのように回避するのか本当にわかりませんが、それは機能します!
SourceForgeページの詳細はこちら:
「NTFSは実際には32,000文字までのパス名をサポートできます。」
7-zipもこのような長い名前をサポートしています。
ただし、SFXコードでは無効になっています。一部のユーザーは、長いパスを使用する方法を理解していないため、長いパスを好みません。これが、SFXコードで無効にした理由です。
およびリリースノート:
9.32 alpha 2013-12-01
- 260文字を超えるファイルパス名のサポートの改善。
4.44ベータ2007-01-20
- 7-Zipは、260文字を超えるファイルパス名をサポートするようになりました。
重要な注意:これを正しく機能させるには、目的のフォルダーにファイルをドラッグアンドドロップするのではなく、7zipの [解凍]ダイアログで宛先パスを直接指定する必要があります。それ以外の場合、「Temp」フォルダは暫定キャッシュとして使用され、Windowsエクスプローラがファイルを「最終的な休止場所」に移動し始めると、同じ260文字の制限に跳ね返ります。詳細については、この質問への回答を参照してください。
それはあり、何らかの理由でデフォルトになっていますが、次のレジストリキーで簡単に上書きできます。
[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/