Skip to content

MS_PathLengthAndEncoding

nishi_74322014 edited this page Sep 1, 2026 · 1 revision

ファイルやパスの文字列長と文字コードの問題

概要

  • GitHub のリポジトリに登録した物件をダウンロードした際、
    取得した ZIP ファイルが解凍できないなどの問題があったので調査をしてみた。

  • ココの問題は、コンピュータに保存されているファイルの識別に用いられる「パス名」に起因する。

    • パス名は,ドライブ文字、ディレクトリパス、ファイル名などを一定の記法に従って連結して表記したもの。
    • Windows のパス名には少々複雑な事情があり、さまざまな注意が必要。

詳細

要因

以下の2つの要因がある(実はファイルシステム側の問題ではなかった)。

ソフトウェアにパス長の制限がある。

Windows の後方互換でパス長の制限があるためパス長の制限があるソフトウェアが現存する。

  • NTFS ファイルシステムが 32K 文字までのパスをサポートしている。

  • しかし、Windows API は、後方互換性を重視するため、

    • パス最大長が MAX_PATH 環境変数で 260 文字に設定されている。
    • パスに \\?\ 接頭辞を使用すると、260 文字を超える文字を使用できる。
    • しかし、一部の Win32 API では \\?\ 接頭辞を使用しても制限が解除されない。

というトコロに原因があるもよう。

  • Windows 10 Version 1607 以降、MAX_PATH の制限を解除できる。
    • レジストリ修正
    • 若しくは、グループポリシー

移行メモ(用語): MAX_PATH は環境変数ではなく
Windows SDK のヘッダーで定義されている定数(260)である。
「環境変数」は誤りだが、著者の言わんとする
「API 側に固定的な上限がある」という趣旨は変わらないため、
記述を残したうえでここに注記する。

補足(制限解除は 3 つ揃って初めて効く): Windows 10 1607 以降の
長いパスの有効化は、次の 3 つが揃って初めて機能する。

  1. レジストリ HKLM\SYSTEM\CurrentControlSet\Control\FileSystem\LongPathsEnabled = 1
    (またはグループ ポリシー「Win32 の長いパスを有効にする」)
  2. アプリケーションのマニフェストに longPathAware の宣言があること
  3. その API が長いパスに対応していること

「レジストリを変えたのに直らない」の多くは 2 が原因である。
なお \\?\ 接頭辞を付ける方法は 1 や 2 がなくても使えるが、
相対パスや ... が解釈されなくなる(後述の「サービス機能」の不活性化)。

全角文字を理解しないソフトウェアがある。

例えば以下のような例。

  • インテル ソフトウェア開発製品 日本語環境でのご注意 | XLsoft エクセルソフト Intel
    https://www.xlsoft.com/jp/products/intel/tech/win_jp_limitation.html
    • プログラム中のファイル入出力について、
      フォルダー名に日本語を含むと正常に動作しない。

    • Microsoft Visual Studio 上でのデバッグ操作において、

      • フォルダー名に日本語がある場合や、
      • ソースコードのファイル名に日本語を含むと、

      ブレークポイントが機能しない

    • , etc.

補足(原因は Unicode 版 API を使っていないこと): Windows の API は
ANSI 版(...A)と Unicode 版(...W)が対になっている。
ANSI 版はシステム ロケールのコードページで文字を解釈するため、
日本語環境では Shift_JIS(CP932)として扱われ、
「表」「ソ」など 2 バイト目が 0x5C\)になる文字で
パスの区切りを誤認する、といった不具合が起きる。
Windows 10 1803 以降は「ワールドワイド言語サポートで
UTF-8 を使用」というベータ機能でコードページを UTF-8 にできるが、
古いアプリが逆に動かなくなることがあるため注意が必要。
詳しくは「文字コード」を参照。

対策

ソフトウェアで対応(ZIPの場合)

  • 上記の双方(パス長
    全角文字)とも、ソフトウェアが対応すれば済む。
  • 例えば、ZIP であれば 7-Zip、WinRAR がコレらの問題に対応している。

パスを変更する。

  • パスを短くする。
    出力パスが短くなるようにする。
    =圧縮した一式の解凍先を C:\temp などとする。

  • パスの全角文字を除く。

その他

以下のようなトピックもある模様。

サービス機能

  • パス名の解釈に伴う「サービス機能」がある。
  • CreateFile() にはいくつものサービス機能がある。

機能一覧(一部)

  1. ディレクトリ区切り文字 / が使用できる。
  2. ディレクトリ区切り文字の重複 \\ が許される。
  3. パス名の途中に \.\ を差し挟める。
  4. パス名の途中に \..\ を差し挟める。
  5. パス名の末尾の . や半角スペースが無視される。

不活性化

\\?\ から始まるパス名についてはサービス機能が働かなくなる。

補足(\\?\ の副作用): 上記のとおり、\\?\ を付けると
パスの正規化が一切行われなくなる。
絶対パスでなければならず、/ も使えないため、
長いパス対策として機械的に付けると別の不具合を招くことがある。
逆に、5 の「末尾の . や空白が無視される」性質を利用すると、
\\?\ 経由でしか削除できない不正な名前のファイルを作れてしまう。

ショートネーム

Windows のファイルやディレクトリは

  • ロングネームと
  • そのロングネームから自動生成されたショートネーム(8.3形式

の2つを持つ。

ショートネーム機能のOFF

レジストリの NtfsDisable8dot3NameCreation で自動生成を OFF にできる。

ショートネームの排除

  • パス名に ~ が含まれていたらショートネームが混入されていると見なす。
  • API でショートネームをロングネームに変換するようにする。

補足(無効化は既存の名前を消さない): NtfsDisable8dot3NameCreation
有効にしても、すでに生成済みのショートネームは残る
既存分を消すには fsutil 8dot3name strip を使う。
古いアプリやインストーラーがショートネームに依存していることがあるため、
一括削除は事前確認が必要。

ストリーム

ファイル名に : が含まれていると具合が悪い。

予約デバイス名

  • MS-DOS の時代に用いられていた古典的な名称

    • コンソール
    • シリアル通信ポート
    • プリンタポートなど
  • 次の名前はディレクトリやファイルの名前には使ってはならない

    • AUX
    • CON
    • NUL
    • PRN
    • CLOCK$
    • COM1COM9
    • LPT1LPT9
  • 10 番以降のデバイス
    先頭に \\.\ を付ける。

補足(拡張子を付けても駄目): 予約デバイス名は
CON.txt のように拡張子を付けても予約名として扱われる
Git や ZIP で Linux 側から作られた aux/ のようなディレクトリが
Windows で展開できないのは、これが理由であることが多い。

参考

パス長の制限

現象

ZIP

その他の遭遇例

  • 色々書き足して行こうと考えていたけど、良いネタが無いかも。

  • 最近遭遇した、現象に、

    • フォルダ名に C# の # が混在していると .NET Core の Build に失敗する。

    • roslyn の完全限定型名は 260 文字、ディレクトリ名は 248 文字以上だと失敗する。

      ---------------------------
      Microsoft Visual Studio
      ---------------------------
      式 "roslyn\%(RecursiveDir)%(Filename)%(Extension)" の中のメタデータを展開できません。
      項目メタデータ "%(Filename)" をパス
      "....\packages\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.2.0.0\build\net46\
      ..\..\tools\roslynlatest\System.Security.Cryptography.X509Certificates.dll"
      に適用できません。指定されたパス、ファイル名、またはその両方が長すぎます。
      完全限定型名は 260 文字未満で指定し、ディレクトリ名は 248 未満で指定してください。
      

    というモノがあった。

    • 後者は「#」→「S」で解決するけど、
    • 前者はフォルダ構成を変更する必要がある。

移行メモ(対応関係): 上記の「後者は #S で解決する」は、
直前の 2 つの箇条書きの**前者(# を含むフォルダ名)**への対処である
(後者はパス長の問題なので # の置換では解決しない)。
著者の記述をそのまま残したうえで注記する。

その他

8.3形式

代替データストリーム(ADS)

ADS: Alternate Data Stream

本 Wiki 内


Tags: インフラストラクチャ, Windows

NetDevInfraWiki

マイクロソフト系技術情報 Wiki
Open 棟梁 Wiki

(未着手)

開発基盤部会 Wiki

移行管理: DONETODO

Clone this wiki locally