Formatos de ruta de acceso de archivo en los sistemas Windows
Los miembros de muchos de los tipos del espacio de nombres System.IO incluyen un parámetro path
que permite especificar una ruta de acceso absoluta o relativa a un recurso de sistema de archivos. Después, esta ruta de acceso se pasa a las API del sistema de archivos de Windows. En este tema se describen los formatos de las rutas de acceso de archivo que se pueden usar en los sistemas Windows.
Rutas de acceso DOS tradicionales
Una ruta de acceso DOS estándar puede constar de tres componentes:
- Una letra de volumen o unidad seguida por el separador de volumen (
:
). - Un nombre de directorio. El carácter separador de directorio separa los subdirectorios dentro de la jerarquía de directorios anidados.
- Un nombre de archivo opcional. El carácter separador de directorio separa la ruta de acceso y el nombre del archivo.
Si los tres componentes están presentes, la ruta de acceso es absoluta. Si no se especifica la letra de volumen o unidad y el nombre de directorio comienza por el carácter separador de directorio, la ruta de acceso es relativa con respecto a la raíz de la unidad actual. En caso contrario, la ruta de acceso es relativa al directorio actual. En la tabla siguiente se muestran algunas rutas de acceso de directorio y archivo posibles.
Ruta de acceso | Descripción |
---|---|
C:\Documents\Newsletters\Summer2018.pdf |
Ruta de acceso de archivo absoluta desde la raíz de la unidad C: . |
\Program Files\Custom Utilities\StringFinder.exe |
Una ruta de acceso relativa desde la raíz de la unidad actual. |
2018\January.xlsx |
Ruta de acceso relativa a un archivo en un subdirectorio del directorio actual. |
..\Publications\TravelBrochure.pdf |
Ruta de acceso relativa a un archivo en un directorio a partir del directorio actual. |
C:\Projects\apilibrary\apilibrary.sln |
Ruta de acceso absoluta a un archivo desde la raíz de la unidad C: . |
C:Projects\apilibrary\apilibrary.sln |
Ruta de acceso relativa desde el directorio actual de la unidad C: . |
Importante
Observe la diferencia entre las dos últimas rutas de acceso. En ambas figura el especificador de volumen opcional (C:
en ambos casos), pero la primera comienza por la raíz del volumen especificado, mientras que la segunda no. Como resultado, la primera es una ruta de acceso absoluta desde el directorio raíz de la unidad C:
, mientras que la segunda es una ruta de acceso relativa desde el directorio actual de la unidad C:
. El uso de la segunda forma cuando está previsto el de la primera suele ser motivo de errores que implican rutas de acceso de archivo de Windows.
Puede determinar si una ruta de acceso de archivo está completa (es decir, si la ruta de acceso es independiente del directorio actual y no cambia cuando cambia el directorio actual) llamando al método Path.IsPathFullyQualified . Tenga en cuenta que una ruta de acceso de este tipo puede incluir segmentos de directorio relativos (.
y ..
) y seguir siendo completa si la ruta de acceso resuelta siempre apunta a la misma ubicación.
En el ejemplo siguiente se muestra la diferencia entre las rutas de acceso absolutas y relativas. Se supone que existe el directorio D:\FY2018\
y que aún no ha establecido ningún directorio actual para D:\
desde el símbolo del sistema antes de ejecutar el ejemplo.
using System;
using System.Diagnostics;
using System.IO;
using System.Reflection;
public class Example2
{
public static void Main(string[] args)
{
Console.WriteLine($"Current directory is '{Environment.CurrentDirectory}'");
Console.WriteLine("Setting current directory to 'C:\\'");
Directory.SetCurrentDirectory(@"C:\");
string path = Path.GetFullPath(@"D:\FY2018");
Console.WriteLine($"'D:\\FY2018' resolves to {path}");
path = Path.GetFullPath(@"D:FY2018");
Console.WriteLine($"'D:FY2018' resolves to {path}");
Console.WriteLine("Setting current directory to 'D:\\Docs'");
Directory.SetCurrentDirectory(@"D:\Docs");
path = Path.GetFullPath(@"D:\FY2018");
Console.WriteLine($"'D:\\FY2018' resolves to {path}");
path = Path.GetFullPath(@"D:FY2018");
// This will be "D:\Docs\FY2018" as it happens to match the drive of the current directory
Console.WriteLine($"'D:FY2018' resolves to {path}");
Console.WriteLine("Setting current directory to 'C:\\'");
Directory.SetCurrentDirectory(@"C:\");
path = Path.GetFullPath(@"D:\FY2018");
Console.WriteLine($"'D:\\FY2018' resolves to {path}");
// This will be either "D:\FY2018" or "D:\FY2018\FY2018" in the subprocess. In the sub process,
// the command prompt set the current directory before launch of our application, which
// sets a hidden environment variable that is considered.
path = Path.GetFullPath(@"D:FY2018");
Console.WriteLine($"'D:FY2018' resolves to {path}");
if (args.Length < 1)
{
Console.WriteLine(@"Launching again, after setting current directory to D:\FY2018");
Uri currentExe = new(Assembly.GetExecutingAssembly().Location, UriKind.Absolute);
string commandLine = $"/C cd D:\\FY2018 & \"{currentExe.LocalPath}\" stop";
ProcessStartInfo psi = new("cmd", commandLine); ;
Process.Start(psi).WaitForExit();
Console.WriteLine("Sub process returned:");
path = Path.GetFullPath(@"D:\FY2018");
Console.WriteLine($"'D:\\FY2018' resolves to {path}");
path = Path.GetFullPath(@"D:FY2018");
Console.WriteLine($"'D:FY2018' resolves to {path}");
}
Console.WriteLine("Press any key to continue... ");
Console.ReadKey();
}
}
// The example displays the following output:
// Current directory is 'C:\Programs\file-paths'
// Setting current directory to 'C:\'
// 'D:\FY2018' resolves to D:\FY2018
// 'D:FY2018' resolves to d:\FY2018
// Setting current directory to 'D:\Docs'
// 'D:\FY2018' resolves to D:\FY2018
// 'D:FY2018' resolves to D:\Docs\FY2018
// Setting current directory to 'C:\'
// 'D:\FY2018' resolves to D:\FY2018
// 'D:FY2018' resolves to d:\FY2018
// Launching again, after setting current directory to D:\FY2018
// Sub process returned:
// 'D:\FY2018' resolves to D:\FY2018
// 'D:FY2018' resolves to d:\FY2018
// The subprocess displays the following output:
// Current directory is 'C:\'
// Setting current directory to 'C:\'
// 'D:\FY2018' resolves to D:\FY2018
// 'D:FY2018' resolves to D:\FY2018\FY2018
// Setting current directory to 'D:\Docs'
// 'D:\FY2018' resolves to D:\FY2018
// 'D:FY2018' resolves to D:\Docs\FY2018
// Setting current directory to 'C:\'
// 'D:\FY2018' resolves to D:\FY2018
// 'D:FY2018' resolves to D:\FY2018\FY2018
Imports System.IO
Imports System.Reflection
Public Module Example2
Public Sub Main(args() As String)
Console.WriteLine($"Current directory is '{Environment.CurrentDirectory}'")
Console.WriteLine("Setting current directory to 'C:\'")
Directory.SetCurrentDirectory("C:\")
Dim filePath As String = Path.GetFullPath("D:\FY2018")
Console.WriteLine($"'D:\\FY2018' resolves to {filePath}")
filePath = Path.GetFullPath("D:FY2018")
Console.WriteLine($"'D:FY2018' resolves to {filePath}")
Console.WriteLine("Setting current directory to 'D:\\Docs'")
Directory.SetCurrentDirectory("D:\Docs")
filePath = Path.GetFullPath("D:\FY2018")
Console.WriteLine($"'D:\\FY2018' resolves to {filePath}")
filePath = Path.GetFullPath("D:FY2018")
' This will be "D:\Docs\FY2018" as it happens to match the drive of the current directory
Console.WriteLine($"'D:FY2018' resolves to {filePath}")
Console.WriteLine("Setting current directory to 'C:\\'")
Directory.SetCurrentDirectory("C:\")
filePath = Path.GetFullPath("D:\FY2018")
Console.WriteLine($"'D:\\FY2018' resolves to {filePath}")
' This will be either "D:\FY2018" or "D:\FY2018\FY2018" in the subprocess. In the sub process,
' the command prompt set the current directory before launch of our application, which
' sets a hidden environment variable that is considered.
filePath = Path.GetFullPath("D:FY2018")
Console.WriteLine($"'D:FY2018' resolves to {filePath}")
If args.Length < 1 Then
Console.WriteLine("Launching again, after setting current directory to D:\FY2018")
Dim currentExe As New Uri(Assembly.GetExecutingAssembly().GetName().CodeBase, UriKind.Absolute)
Dim commandLine As String = $"/C cd D:\FY2018 & ""{currentExe.LocalPath}"" stop"
Dim psi As New ProcessStartInfo("cmd", commandLine)
Process.Start(psi).WaitForExit()
Console.WriteLine("Sub process returned:")
filePath = Path.GetFullPath("D:\FY2018")
Console.WriteLine($"'D:\\FY2018' resolves to {filePath}")
filePath = Path.GetFullPath("D:FY2018")
Console.WriteLine($"'D:FY2018' resolves to {filePath}")
End If
Console.WriteLine("Press any key to continue... ")
Console.ReadKey()
End Sub
End Module
' The example displays the following output:
' Current directory is 'C:\Programs\file-paths'
' Setting current directory to 'C:\'
' 'D:\FY2018' resolves to D:\FY2018
' 'D:FY2018' resolves to d:\FY2018
' Setting current directory to 'D:\Docs'
' 'D:\FY2018' resolves to D:\FY2018
' 'D:FY2018' resolves to D:\Docs\FY2018
' Setting current directory to 'C:\'
' 'D:\FY2018' resolves to D:\FY2018
' 'D:FY2018' resolves to d:\FY2018
' Launching again, after setting current directory to D:\FY2018
' Sub process returned:
' 'D:\FY2018' resolves to D:\FY2018
' 'D:FY2018' resolves to d:\FY2018
' The subprocess displays the following output:
' Current directory is 'C:\'
' Setting current directory to 'C:\'
' 'D:\FY2018' resolves to D:\FY2018
' 'D:FY2018' resolves to D:\FY2018\FY2018
' Setting current directory to 'D:\Docs'
' 'D:\FY2018' resolves to D:\FY2018
' 'D:FY2018' resolves to D:\Docs\FY2018
' Setting current directory to 'C:\'
' 'D:\FY2018' resolves to D:\FY2018
' 'D:FY2018' resolves to D:\FY2018\FY2018
Rutas de acceso UNC
Las rutas de acceso de convención de nomenclatura universal (UNC), que se usan para acceder a los recursos de red, tienen el formato siguiente:
- Un nombre de servidor o host que va precedido por
\\
. El nombre del servidor puede ser un nombre de equipo NetBIOS o una dirección IP o FQDN (se admiten tanto IPv4 como v6). - Un nombre de recurso compartido, que se separa del nombre de host mediante
\
. Juntos, el nombre del servidor y el del recurso compartido forman el volumen. - Un nombre de directorio. El carácter separador de directorio separa los subdirectorios dentro de la jerarquía de directorios anidados.
- Un nombre de archivo opcional. El carácter separador de directorio separa la ruta de acceso y el nombre del archivo.
A continuación se muestran algunos ejemplos de rutas de acceso UNC:
Ruta de acceso | Descripción |
---|---|
\\system07\C$\ |
Directorio raíz de la unidad C: en system07 . |
\\Server2\Share\Test\Foo.txt |
Archivo Foo.txt en el directorio Prueba del volumen \\Server2\Share . |
Las rutas de acceso UNC siempre deben ser completas. Pueden incluir segmentos de directorio relativos (.
y ..
), pero estos deben formar parte de una ruta de acceso completa. Solo puede usar rutas de acceso relativas mediante la asignación de una ruta de acceso UNC a una letra de unidad.
Rutas de acceso de dispositivo DOS
El sistema operativo Windows tiene un modelo de objetos unificado que apunta a todos los recursos, incluidos los archivos. Estas rutas de acceso de objeto son accesibles desde la ventana de consola y se exponen a la capa de Win32 a través de una carpeta especial para vínculos simbólicos a la que se asignan las rutas de acceso DOS y UNC heredadas. A esta carpeta especial se accede a través de la sintaxis de ruta de acceso de dispositivo DOS, que es una de las siguientes:
\\.\C:\Test\Foo.txt
\\?\C:\Test\Foo.txt
Además de identificar una unidad por su letra de unidad, puede identificar un volumen mediante su GUID de volumen. Esto toma la forma:
\\.\Volume{b75e2c83-0000-0000-0000-602f00000000}\Test\Foo.txt
\\?\Volume{b75e2c83-0000-0000-0000-602f00000000}\Test\Foo.txt
Nota
La sintaxis de ruta de acceso de dispositivo DOS es compatible con las implementaciones de .NET que se ejecutan en Windows a partir de .NET Core 1.1 y .NET Framework 4.6.2.
La ruta de acceso de dispositivo DOS consta de los componentes siguientes:
El especificador de ruta de acceso de dispositivo (
\\.\
o\\?\
), que identifica la ruta de acceso como una ruta de acceso de dispositivo DOS.Nota
\\?\
se admite en todas las versiones de .NET Core, y .NET 5 y versiones posteriores, y en .NET Framework a partir de la versión 4.6.2.Un vínculo simbólico para el objeto de dispositivo "real" (C: en el caso de un nombre de unidad o Volume{b75e2c83-0000-0000-0000-602f00000000} en el caso de un identificador de volumen).
El primer segmento de la ruta de acceso de dispositivo DOS, una vez que el especificador de ruta de acceso de dispositivo identifica el volumen o la unidad. (Por ejemplo,
\\?\C:\
y\\.\BootPartition\
).Existe un vínculo específico para las UNC que, de forma lógica, se denomina
UNC
. Por ejemplo:\\.\UNC\Server\Share\Test\Foo.txt
\\?\UNC\Server\Share\Test\Foo.txt
Para las UNC de dispositivo, la parte del servidor o recurso compartido forma el volumen. Por ejemplo, en
\\?\server1\utilities\\filecomparer\
, la parte del servidor o recurso compartido esserver1\utilities
. Esto es importante cuando se llama a un método como Path.GetFullPath(String, String) con segmentos de directorio relativos, pues nunca se puede ir más allá del volumen.
Las rutas de acceso del dispositivo DOS están completas por definición y no pueden comenzar con un segmento de directorio relativo (.
o ..
). Los directorios actuales nunca entran en uso.
Ejemplo: Formas de hacer referencia al mismo archivo
En el ejemplo siguiente se muestran algunas formas de hacer referencia a un archivo cuando se usan las API del espacio de nombres System.IO. En el ejemplo se crea una instancia de un objeto FileInfo y se usan sus propiedades Name y Length para mostrar el nombre y la longitud del archivo.
using System;
using System.IO;
class Program
{
static void Main()
{
string[] filenames = {
@"c:\temp\test-file.txt",
@"\\127.0.0.1\c$\temp\test-file.txt",
@"\\LOCALHOST\c$\temp\test-file.txt",
@"\\.\c:\temp\test-file.txt",
@"\\?\c:\temp\test-file.txt",
@"\\.\UNC\LOCALHOST\c$\temp\test-file.txt" };
foreach (string filename in filenames)
{
FileInfo fi = new(filename);
Console.WriteLine($"file {fi.Name}: {fi.Length:N0} bytes");
}
}
}
// The example displays output like the following:
// file test-file.txt: 22 bytes
// file test-file.txt: 22 bytes
// file test-file.txt: 22 bytes
// file test-file.txt: 22 bytes
// file test-file.txt: 22 bytes
// file test-file.txt: 22 bytes
Imports System.IO
Module Program
Sub Main()
Dim filenames() As String = {
"c:\temp\test-file.txt",
"\\127.0.0.1\c$\temp\test-file.txt",
"\\LOCALHOST\c$\temp\test-file.txt",
"\\.\c:\temp\test-file.txt",
"\\?\c:\temp\test-file.txt",
"\\.\UNC\LOCALHOST\c$\temp\test-file.txt"}
For Each filename In filenames
Dim fi As New FileInfo(filename)
Console.WriteLine($"file {fi.Name}: {fi.Length:N0} bytes")
Next
End Sub
End Module
Normalización de la ruta de acceso
Casi todas las rutas de acceso que se pasan a las API de Windows se normalizan. Durante la normalización, Windows realiza los pasos siguientes:
- Identifica la ruta de acceso.
- Aplica el directorio actual a rutas de acceso parciales (relativas).
- Aplica formato canónico a los separadores de componentes y directorios.
- Evalúa los componentes de directorio relativos (
.
para el directorio actual y..
para el directorio principal). - Recorta determinados caracteres.
Esta normalización se produce de manera implícita, pero se puede realizar de forma explícita mediante una llamada al método Path.GetFullPath, que encapsula una llamada a la función GetFullPathName(). También se puede llamar directamente a la función GetFullPathName() de Windows mediante P/Invoke.
Identificación de la ruta de acceso
El primer paso de la normalización de la ruta de acceso consiste en identificar el tipo de ruta de acceso. Las rutas de acceso se incluyen en una de estas categorías:
- Son rutas de acceso de dispositivo; es decir, comienzan con dos separadores y un signo de interrogación o un punto (
\\?
o\\.
). - Son rutas de acceso UNC, es decir, comienzan por dos separadores sin un signo de interrogación o un punto.
- Son rutas de acceso DOS completas, es decir, comienzan por una letra de unidad, un separador de volumen y un separador de componentes (
C:\
). - Designan un dispositivo heredado (
CON
,LPT1
). - Son relativas a la raíz de la unidad actual; es decir, comienzan con un único separador de componente (
\
). - Son relativas al directorio actual de una unidad especificada, es decir, comienzan por una letra de unidad, un separador de volumen y ningún separador de componente (
C:
). - Son relativas al directorio actual, es decir, comienzan por cualquier otro elemento (
temp\testfile.txt
).
El tipo de la ruta de acceso determina si se aplica o no un directorio actual de alguna manera. También determina lo que es la "raíz" de la ruta de acceso.
Control de dispositivos heredados
Si la ruta de acceso es un dispositivo DOS heredado como CON
, COM1
o LPT1
, se convierte en una ruta de acceso de dispositivo mediante la anteposición \\.\
y se devuelve.
Antes de Windows 11, una ruta de acceso que comienza por un nombre de dispositivo heredado se interpreta siempre como un dispositivo heredado por el método Path.GetFullPath(String). Por ejemplo la ruta de acceso de dispositivo DOS para CON.TXT
es \\.\CON
, y la de COM1.TXT\file1.txt
es \\.\COM1
. Dado que esto ya no se aplica con Windows 11, especifique la ruta de acceso completa al dispositivo DOS heredado, como \\.\CON
.
Aplicación del directorio actual
Si una ruta de acceso no es completa, Windows le aplica el directorio actual. El directorio actual no se aplica a las rutas de acceso de dispositivo y UNC. Ni tampoco una unidad completa con separador C:\
.
Si la ruta de acceso comienza por un único separador de componente, se aplica la unidad desde el directorio actual. Por ejemplo, si la ruta de acceso de archivo es \utilities
y el directorio actual es C:\temp\
, la normalización genera C:\utilities
.
Si la ruta de acceso comienza por una letra de unidad, el separador de volumen y ningún separador de componente, se aplica el último directorio actual establecido desde el shell de comandos para la unidad especificada. Si no se estableció el último directorio actual, solo se aplica la unidad. Por ejemplo, si la ruta de acceso de archivo es D:sources
, el directorio actual es C:\Documents\
y el último directorio actual en la unidad D: era D:\sources\
, el resultado es D:\sources\sources
. Estas rutas de acceso "relativas a la unidad" son un origen común de errores lógicos de programas y scripts. Asumir que una ruta de acceso que comienza con una letra y dos puntos no es relativa evidentemente no es correcto.
Si la ruta de acceso comienza por un valor distinto de un separador, se aplican la unidad y el directorio actuales. Por ejemplo, si la ruta de acceso es filecompare
y el directorio actual es C:\utilities\
, el resultado es C:\utilities\filecompare\
.
Importante
El uso de rutas de acceso relativas en las aplicaciones multiproceso (es decir, en la mayoría de aplicaciones) es peligroso, porque el directorio actual es un valor de cada proceso. Cualquier subproceso puede cambiar el directorio actual en cualquier momento. A partir de .NET Core 2.1, se puede llamar al método Path.GetFullPath(String, String) para obtener una ruta de acceso absoluta a partir de una ruta de acceso relativa y la ruta de acceso base (el directorio actual) sobre la que se quiere resolver.
Asignación canónica de separadores
Todas las barras diagonales (/
) se convierten en el separador estándar de Windows, que es la barra diagonal inversa (\
). Si están presentes, una serie de barras diagonales que siguen a las dos primeras barras diagonales se contraen en una sola barra diagonal.
Nota:
A partir de .NET 8 en sistemas operativos basados en Unix, el tiempo de ejecución ya no convierte caracteres de barra diagonal inversa (\
) en separadores de directorios (barras diagonales /
). Para obtener más información, consulte Asignación de barras diagonales inversas en rutas de acceso de archivo Unix.
Evaluación de componentes relativos
Cuando se procesa la ruta de acceso, se evalúan los componentes o segmentos que se componen de un punto o un punto doble (.
o ..
):
Para un punto, se quita el segmento actual, ya que hace referencia al directorio actual.
Para un punto doble, se quitan el segmento actual y el principal, ya que el punto doble hace referencia al directorio principal.
Los directorios principales solo se quitan si no están después de la raíz de la ruta de acceso. La raíz de la ruta de acceso depende del tipo de ruta de acceso. Es la unidad (
C:\
) para las rutas de acceso DOS, el servidor o recurso compartido para las UNC (\\Server\Share
), y el prefijo de ruta de acceso de dispositivo para las rutas de acceso de dispositivo (\\?\
o\\.\
).
Recorte de caracteres
Junto con las ejecuciones de los separadores y segmentos relativos que se han quitado anteriormente, durante la normalización se quitan algunos caracteres adicionales:
Si un segmento termina en un punto, se quita ese punto. (Un segmento de un punto o de dos se normaliza en el paso anterior. Un segmento de tres o más puntos no se normaliza y es realmente un nombre de archivo o directorio válido).
Si la ruta de acceso no termina en un separador, se quitan todos los puntos y espacios finales (U+0020). Si el último segmento es simplemente un punto o un punto doble, se aplica la regla anterior de componentes relativos.
Esta regla significa que se puede crear un nombre de directorio con un espacio final si se agrega un separador final después del espacio.
Importante
Nunca se debe crear un nombre de archivo o directorio con un espacio final. Los espacios finales pueden dificultar o impedir el acceso a un directorio, y se suelen producir errores en las aplicaciones cuando se intenta controlar directorios o archivos con nombres que incluyen espacios.
Omisión de la normalización
Normalmente, todas las rutas de acceso que se pasan a una API de Windows se pasan (de forma efectiva) a la función GetFullPathName y se normalizan. Hay una excepción importante: una ruta de acceso de dispositivo que comienza con un signo de interrogación en lugar de un punto. A menos que la ruta de acceso comience exactamente con \\?\
(observe el uso de la barra diagonal inversa canónica), se normaliza.
¿Por qué querría omitir la normalización? Hay tres razones principales:
Para obtener acceso a las rutas de acceso que normalmente no están disponibles pero que son válidas. A un archivo o directorio denominado
hidden.
, por ejemplo, no se puede acceder de otra forma.Para mejorar el rendimiento omitiendo la normalización, si ya se ha normalizado.
Solo en .NET Framework, para omitir la comprobación
MAX_PATH
de la longitud de ruta de acceso para permitir rutas de acceso que tienen más de 259 caracteres. En la mayoría de API se permite esto, con algunas excepciones.
Nota
En .NET Core, y .NET 5 y versiones posteriores, las rutas de acceso largas se administran de forma implícita y no se realiza una comprobación MAX_PATH
. La comprobación MAX_PATH
solo se aplica a .NET Framework.
La omisión de la normalización y las comprobaciones de ruta de acceso máximas es la única diferencia entre las dos sintaxis de ruta de acceso de dispositivo. En los demás casos son idénticas. Tenga cuidado al omitir la normalización, dado que es muy fácil crear rutas de acceso difíciles de controlar para las aplicaciones "normales".
Las rutas de acceso que empiezan por \\?\
se siguen normalizando si se pasan de forma explícita a la función GetFullPathName.
Puede pasar rutas de acceso de más de MAX_PATH
caracteres a GetFullPathName sin \\?\
. Admite rutas de acceso de longitud arbitraria hasta el tamaño de cadena máximo admitido por Windows.
Las mayúsculas y minúsculas y el sistema de archivos de Windows
Una peculiaridad del sistema de archivos de Windows que resulta confuso para los usuarios y desarrolladores que no usan Windows es que los nombres de ruta de acceso y directorio no distinguen mayúsculas de minúsculas. Es decir, los nombres de archivos y directorios reflejan las mayúsculas y minúsculas de las cadenas que se usan cuando se crean. Por ejemplo, la llamada al método
Directory.Create("TeStDiReCtOrY");
Directory.Create("TeStDiReCtOrY")
crea un directorio denominado TeStDiReCtOrY. Si modifica el nombre de un directorio o archivo para cambiar sus mayúsculas y minúsculas, el nombre del directorio o archivo refleja las mayúsculas y minúsculas de la cadena usada al cambiar el nombre. Por ejemplo, en el código siguiente se cambia el nombre de un archivo de test.txt a Test.txt:
using System.IO;
class Example3
{
static void Main()
{
var fi = new FileInfo(@".\test.txt");
fi.MoveTo(@".\Test.txt");
}
}
Imports System.IO
Module Example3
Public Sub Main()
Dim fi As New FileInfo(".\test.txt")
fi.MoveTo(".\Test.txt")
End Sub
End Module
Pero las comparaciones de nombre de directorio y archivo no distinguen mayúsculas de minúsculas. Si busca un archivo denominado "test.txt", las API del sistema de archivos de .NET ignoran las mayúsculas y minúsculas en la comparación. "Test.txt", "TEST.TXT", "test.TXT" y cualquier otra combinación de letras mayúsculas y minúsculas coincidirán con "test.txt".