¿Por qué existe el límite de longitud de ruta de 260 caracteres en Windows?

Me he encontrado con este problema algunas veces en momentos inoportunos:

  • tratando de trabajar en proyectos de código abierto de Java con rutas profundas
  • Almacenando árboles Wiki profundos de Fitnesse en el control de la fuente
  • Un error al intentar usar Bazar para importar mi árbol de control de fuente

¿Por qué existe este límite?

¿Por qué no ha sido eliminado aún?

¿Cómo lidias con el límite de ruta? … y no, cambiar a Linux o Mac OS X no es una respuesta válida a esta pregunta;)

Citando este artículo http://msdn.microsoft.com/en-us/library/aa365247(VS.85).aspx#maxpath

Límite máximo de longitud de ruta

En la API de Windows (con algunas excepciones explicadas en los párrafos siguientes), la longitud máxima para una ruta es MAX_PATH , que se define como 260 caracteres. Una ruta local está estructurada en el siguiente orden: letra de unidad, dos puntos, barra invertida, componentes de nombre separados por barras invertidas y un carácter nulo de terminación. Por ejemplo, la ruta máxima en la unidad D es “D: \ alguna cadena de ruta de 256 caracteres ” donde “” representa el carácter nulo de terminación invisible para la página de códigos del sistema actual. (Los caracteres <> se utilizan aquí para claridad visual y no pueden ser parte de una cadena de ruta válida.)

Ahora vemos que es 1 + 2 + 256 + 1 o [unidad] [: \] [ruta] [nulo] = 260. Se podría suponer que 256 es una longitud de cadena fija razonable a partir de los días de DOS. Y volviendo a las API DOS nos damos cuenta de que el sistema rastreó la ruta actual por unidad, y tenemos 26 (32 con símbolos) unidades máximas (y directorios actuales).

El INT 0x21 AH = 0x47 dice “Esta función devuelve la descripción de la ruta sin la letra de la unidad y la barra invertida inicial.” Así que vemos que el sistema almacena el CWD como un par (unidad, ruta) y usted solicita la ruta especificando el unidad (1 = A, 2 = B, …), si especifica un 0, asume que la ruta del disco devuelto por INT 0x21 AH = 0x15 AL = 0x19. Entonces ahora sabemos por qué es 260 y no 256, porque esos 4 bytes no están almacenados en la cadena de ruta.

Por qué una cadena de ruta de 256 bytes, porque 640K es suficiente RAM.

Esto no es estrictamente cierto ya que el sistema de archivos NTFS admite rutas de hasta 32k caracteres. Puede utilizar el api win32 y el prefijo ” \\?\ ” En la ruta para usar más de 260 caracteres.

Una explicación detallada del camino largo del blog del equipo .Net BCL .
Un pequeño extracto destaca el problema con los caminos largos

Otra preocupación es el comportamiento inconsistente que resultaría al exponer el soporte de ruta larga. Las rutas largas con el prefijo \\?\ Se pueden usar en la mayoría de las API de Windows relacionadas con archivos, pero no en todas las API de Windows. Por ejemplo, LoadLibrary, que asigna un módulo a la dirección del proceso de llamada, falla si el nombre del archivo es más largo que MAX_PATH. Esto significa que MoveFile le permitirá mover una DLL a una ubicación tal que su ruta de acceso tenga más de 260 caracteres, pero cuando intente cargar la DLL, fallará. Hay ejemplos similares en todas las API de Windows; existen algunas soluciones, pero están basadas en cada caso.

La pregunta es por qué todavía existe la limitación. Sin duda, Windows moderno puede boost el lado de MAX_PATH para permitir rutas más largas. ¿Por qué no se ha eliminado la limitación?

  • La razón por la que no se puede eliminar es que Windows prometió que nunca cambiaría.

A través del contrato de API, Windows ha garantizado todas las aplicaciones que las API de archivo estándar nunca devolverán una ruta de más de 260 caracteres.

Considere el siguiente código correcto :

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

Windows garantizó mi progtwig que WIN32_FIND_DATA mi estructura WIN32_FIND_DATA :

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

Mi aplicación no declaró el valor de la constante MAX_PATH , la API de Windows sí. Mi aplicación usó ese valor definido.

Mi estructura está definida correctamente y solo asigna 592 bytes en total. Eso significa que solo puedo recibir un nombre de archivo de menos de 260 caracteres. Windows me prometió que si escribía mi aplicación correctamente, mi aplicación continuaría funcionando en el futuro.

Si Windows permitiera nombres de archivos de más de 260 caracteres, mi aplicación existente (que utilizaba correctamente la API correcta) fallaría.

Para cualquiera que MAX_PATH a Microsoft que cambie la constante MAX_PATH , primero debe asegurarse de que ninguna aplicación existente falle. Por ejemplo, todavía tengo y uso una aplicación de Windows que se escribió para ejecutarse en Windows 3.11. Todavía se ejecuta en Windows 10 de 64 bits. Eso es lo que te ofrece la compatibilidad con versiones anteriores.

Microsoft creó una forma de usar los 32,768 nombres de ruta completos; pero tuvieron que crear un nuevo contrato API para hacerlo. Por un lado, debe usar la API de Shell para enumerar archivos (ya que no todos los archivos existen en un disco duro o recurso compartido de red).

Pero también tienen que no romper las aplicaciones de usuario existentes. La gran mayoría de las aplicaciones no utilizan la API api para el trabajo de archivos. Todo el mundo simplemente llama a FindFirstFile / FindNextFile y lo llama al día.

Desde Windows 10. puede eliminar la limitación modificando una clave de registro.

Consejo A partir de Windows 10, versión 1607, las limitaciones MAX_PATH se han eliminado de las funciones comunes de archivos y directorios de Win32. Sin embargo, debe optar por el nuevo comportamiento.

Una clave de registro le permite habilitar o deshabilitar el nuevo comportamiento de ruta larga. Para habilitar el comportamiento de ruta larga establezca la clave de registro en HKLM\SYSTEM\CurrentControlSet\Control\FileSystem LongPathsEnabled (Type: REG_DWORD ). El sistema almacenará en caché el valor de la clave (por proceso) después de la primera llamada a una función de directorio o archivo Win32 afectado (la lista sigue). La clave de registro no se volverá a cargar durante la vida del proceso. Para que todas las aplicaciones en el sistema reconozcan el valor de la clave, podría ser necesario reiniciar porque algunos procesos pueden haber comenzado antes de que se estableciera la clave. La clave de registro también se puede controlar a través de la Política de grupo en Computer Configuration > Administrative Templates > System > Filesystem > Enable NTFS long paths . También puede habilitar el nuevo comportamiento de ruta larga por aplicación a través del manifiesto:

   true   

Puede montar una carpeta como una unidad. Desde la línea de comandos, si tiene una ruta de acceso C:\path\to\long\folder , puede asignarla a la letra de unidad X: usando:

 subst x: \path\to\long\folder 

Una forma de hacer frente al límite de ruta es acortar las entradas de ruta con enlaces simbólicos.

Por ejemplo:

  1. crea un directorio C:\p para mantener enlaces cortos a rutas largas
  2. mklink /JC:\p\foo C:\Some\Crazy\Long\Path\foo
  3. agregue C:\p\foo a su ruta en lugar de la ruta larga

En cuanto a por qué esto todavía existe, MS no lo considera una prioridad, y valora la compatibilidad con versiones anteriores sobre el avance de su sistema operativo (al menos en este caso).

Una solución alternativa que uso es usar los “nombres cortos” para los directorios en la ruta, en lugar de sus versiones estándar legibles por el ser humano. Por ejemplo, para C:\Program Files\ C:\PROGRA~1\ Puede encontrar los equivalentes de nombre corto usando dir /x .

En cuanto a cómo hacer frente a la limitación del tamaño de la ruta en Windows, usar 7zip para empaquetar (y descomprimir) los archivos sensibles a la longitud de la ruta parece una solución viable. Lo he usado para transportar varias instalaciones IDE (esas rutas de plugins de Eclipse, ¡ay!) Y montones de documentación autogenerada y hasta ahora no he tenido ningún problema.

No estoy seguro de cómo evade el límite de 260 caracteres establecido por Windows (desde un PoV técnico), pero bueno, ¡funciona!

Más detalles en su página de SourceForge aquí :

“NTFS realmente puede admitir nombres de ruta de hasta 32,000 caracteres de longitud”.

7-zip también admite nombres tan largos.

Pero está deshabilitado en el código SFX. A algunos usuarios no les gustan los caminos largos, ya que no entienden cómo trabajar con ellos. Es por eso que lo he desactivado en código SFX.

y notas de la versión :

9.32 alpha 2013-12-01

  • Soporte mejorado para rutas de archivos de más de 260 caracteres.

4.44 beta 2007-01-20

  • 7-Zip ahora admite nombres de rutas de archivos de más de 260 caracteres.

NOTA IMPORTANTE: Para que esto funcione correctamente, deberá especificar la ruta de destino en el cuadro de diálogo 7zip “Extraer” directamente, en lugar de arrastrar y soltar los archivos en la carpeta deseada. De lo contrario, la carpeta “Temp” se usará como un caché provisional y rebotarás en la misma limitación de 260 caracteres una vez que Windows Explorer comience a mover los archivos a su “lugar de descanso final”. Vea las respuestas a esta pregunta para más información.

Otra forma de lidiar con esto es usar Cygwin, dependiendo de qué desea hacer con los archivos (es decir, si los comandos de Cygwin se ajustan a sus necesidades)

Por ejemplo, permite copiar, mover o renombrar archivos que incluso Windows Explorer no puede. O, por supuesto, tratar con los contenidos de ellos como md5sum, grep, gzip, etc.

También para los progtwigs que está codificando, podría vincularlos a la DLL de Cygwin y les permitiría usar rutas largas (aunque no lo he probado)

Sí, y es un valor predeterminado por alguna razón, pero podría anularlo fácilmente con esta clave de registro:

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

Ver: https://blogs.msdn.microsoft.com/jeremykuhne/2016/07/30/net-4-6-2-and-long-paths-on-windows-10/

Puede habilitar nombres de ruta larga utilizando PowerShell:

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

Otra versión es usar una Política de grupo en Computer Configuration / Administrative Templates / System / System Filesystem :

Editor de políticas grupales

Mientras todos lloran que 260 caracteres son horribles en 2017, de alguna manera nadie llora que la mayoría de gnu shitware se rompa si encuentra espacios en los caminos. Ni siquiera unicode. Y hablando de funciones inherentemente rotas, piense en su strcpy favorito sin la n . Incluso malloc está roto en Linux porque se basa en fallas de página para comprometer realmente el espacio de direcciones reservado (que es lento y propenso a errores). Nadie es perfecto, y la ignorancia no es una razón válida para gimotear.

Además, los comentaristas de alguna manera no dicen qué está roto exactamente.

Hay 3 cosas que están rotas:

  • ciertas llamadas (solo estoy al tanto de Get / SetCurrentDirectoryW) están limitadas a un único hilo y 260 caracteres sin importar qué. Así que las rutas esencialmente relativas están rotas en Windows, emúlelas igual que emula la fork si se ve obligado a hacerlo.

  • el software portado desde no ventanas que inherentemente se basa en conceptos que no son de Windows (incluido el concepto de directorio actual / rutas relativas, ver arriba)

  • el software que está escrito desde cero para Windows, pero aún usa una antigua API (pero vea arriba; mientras que hay API para el acceso general al sistema de archivos, no hay API para el directorio actual en Windows que funciona más allá de MAX_PATH)

En cuanto a por qué todavía está roto, en mi opinión, MS arregló todo lo que es reparable. Creo que es herencia del directorio actual por procesos secundarios que no permite que GetCurrentDirectoryW sea reparado.