Formati dei percorsi di file nei sistemi WindowsFile path formats on Windows systems

I membri di molti tipi nello spazio dei nomi System.IO includono un parametro path che consente di specificare un percorso assoluto o relativo di una risorsa del file system.Members of many of the types in the System.IO namespace include a path parameter that lets you specify an absolute or relative path to a file system resource. Questo percorso viene quindi passato alle API del file system Windows.This path is then passed to Windows file system APIs. Questo argomento descrive i formati per i percorsi di file che è possibile usare nei sistemi Windows.This topic discusses the formats for file paths that you can use on Windows systems.

Percorsi DOS tradizionaliTraditional DOS paths

Un percorso DOS standard può essere costituito da tre componenti:A standard DOS path can consist of three components:

Se sono presenti tutti e tre i componenti, il percorso è assoluto.If all three components are present, the path is absolute. Se non si specifica alcun volume o lettera di unità e il nome della directory inizia con il carattere separatore di directory, il percorso è relativo dalla radice dell'unità corrente.If no volume or drive letter is specified and the directory name begins with the directory separator character, the path is relative from the root of the current drive. In caso contrario, il percorso è relativo alla directory corrente.Otherwise, the path is relative to the current directory. La tabella seguente illustra alcuni percorsi possibili di directory e file.The following table shows some possible directory and file paths.

PercorsoPath DescrizioneDescription
C:\Documents\Newsletters\Summer2018.pdf Percorso file assoluto dalla radice dell'unità C:An absolute file path from the root of drive C:
\Program Files\Custom Utilities\StringFinder.exe Percorso assoluto dalla radice dell'unità corrente.An absolute path from the root of the current drive.
2018\January.xlsx Percorso relativo a un file in una sottodirectory della directory corrente.A relative path to a file in a subdirectory of the current directory.
..\Publications\TravelBrochure.pdf Percorso relativo a un file in una directory che è un peer della directory corrente.A relative path to file in a directory that is a peer of the current directory.
C:\Projects\apilibrary\apilibrary.sln Percorso assoluto a un file dalla radice dell'unità C:An absolute path to a file from the root of drive C:
C:Projects\apilibrary\apilibrary.sln Percorso relativo dalla directory corrente dell'unità C:A relative path from the current directory of the C: drive.

Importante

Si noti la differenza tra gli ultimi due percorsi.Note the difference between the last two paths. Entrambi specificano l'identificatore di volume facoltativo (C: in entrambi i casi), ma il primo inizia con la radice del volume specificato, mentre il secondo no.Both specify the optional volume specifier (C: in both cases), but the first begins with the root of the specified volume, whereas the second does not. Di conseguenza, il primo è un percorso assoluto dalla directory radice dell'unità C:, mentre il secondo è un percorso relativo dalla directory corrente dell'unità C:.As result, the first is an absolute path from the root directory of drive C:, whereas the second is a relative path from the current directory of drive C:. L'uso del secondo formato quando si intende usare il primo è una fonte comune di bug per i percorsi di file Windows.Use of the second form when the first is intended is a common source of bugs that involve Windows file paths.

È possibile determinare se un percorso di file è completo (ovvero se il percorso è indipendente dalla directory corrente e non cambia quando la directory corrente viene modificata) chiamando il metodo IsPathFullyQualified.You can determine whether a file path is fully qualified (that is, it the path is independent of the current directory and does not change when the current directory changes) by calling the IsPathFullyQualified method. Si noti che tale percorso può includere segmenti di directory relativi (. e ..) ed essere comunque completo se il percorso risolto punta sempre alla stessa posizione.Note that such a path can include relative directory segments (. and ..) and still be fully qualified if the resolved path always points to the same location.

L'esempio seguente illustra la differenza fra percorsi assoluti e relativi.The following example illustrates the difference between absolute and relative paths. Si presuppone che la directory D:\FY2018\ esista e che non sia stata impostata alcuna directory corrente per D:\ dal prompt dei comandi prima di eseguire l'esempio.It assumes that the directory D:\FY2018\ exists, and that you haven't set any current directory for D:\ from the command prompt before running the example.

using System;
using System.Diagnostics;
using System.IO;
using System.Reflection;

public class Example
{
   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 Uri(Assembly.GetExecutingAssembly().GetName().CodeBase, UriKind.Absolute);
         string commandLine = $"/C cd D:\\FY2018 & \"{currentExe.LocalPath}\" stop";
         ProcessStartInfo psi = new ProcessStartInfo("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.Diagnostics
Imports System.IO
Imports System.Reflection

Public Module Example

    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

Per visualizzare i commenti del codice tradotti in lingue diverse dall'inglese, segnalare il problema in questo argomento di discussione su GitHub.If you would like to see code comments translated to languages other than English, let us know in this GitHub discussion issue.

Percorsi UNCUNC paths

I percorsi UNC (Universal Naming Convention), che vengono usati per accedere alle risorse di rete, hanno il formato seguente:Universal naming convention (UNC) paths, which are used to access network resources, have the following format:

  • Un nome host o server, preceduto da \\.A server or host name, which is prefaced by \\. Il nome del server può essere un nome computer NetBIOS o un indirizzo IP/FQDN (sono supportati IPv4 e v6).The server name can be a NetBIOS machine name or an IP/FQDN address (IPv4 as well as v6 are supported).
  • Un nome condivisione, separato dal nome host da \.A share name, which is separated from the host name by \. Insieme, il server e il nome condivisione costituiscono il volume.Together, the server and share name make up the volume.
  • Nome di directory.A directory name. Il carattere separatore di directory separa le sottodirectory all'interno della gerarchia di directory annidata.The directory separator character separates subdirectories within the nested directory hierarchy.
  • Un nome file facoltativo.An optional filename. Il carattere separatore di directory separa il percorso e il nome del file.The directory separator character separates the file path and the filename.

Di seguito sono riportati alcuni esempi di percorsi UNC:The following are some examples of UNC paths:

PercorsoPath DescrizioneDescription
\\system07\C$\ Directory radice dell'unità C: in system07.The root directory of the C: drive on system07.
\\Server2\Share\Test\Foo.txt File Foo.txt nella directory Test del volume \\Server2\Share.The Foo.txt file in the Test directory of the \\Server2\Share volume.

I percorsi UNC devono essere sempre completi.UNC paths must always be fully qualified. Possono includere segmenti di directory relativi (. e ..), ma devono far parte di un percorso completo.They can include relative directory segments (. and ..), but these must be part of a fully qualified path. È possibile usare i percorsi relativi solo eseguendo il mapping di un percorso UNC a una lettera di unità.You can use relative paths only by mapping a UNC path to a drive letter.

Percorsi del dispositivo DOSDOS device paths

Il sistema operativo Windows ha un modello a oggetti unificato che punta a tutte le risorse, inclusi i file.The Windows operating system has a unified object model that points to all resources, including files. Questi percorsi degli oggetti sono accessibili dalla finestra della console e vengono esposti al livello Win32 tramite una cartella speciale di collegamenti simbolici a cui sono mappati i percorsi UNC e DOS legacy.These object paths are accessible from the console window and are exposed to the Win32 layer through a special folder of symbolic links that legacy DOS and UNC paths are mapped to. Questa cartella speciale è accessibile tramite la sintassi del percorso del dispositivo DOS, ovvero uno dei due riportati di seguito:This special folder is accessed via the DOS device path syntax, which is one of:

\\.\C:\Test\Foo.txt \\?\C:\Test\Foo.txt

Oltre a identificare un'unità con la relativa lettera di unità, è possibile identificare un volume usando l'identificatore univoco globale (GUID) del volume.In addition to identifying a drive by its drive letter, you can identify a volume by using its volume GUID. Assume il formato:This takes the form:

\\.\Volume{b75e2c83-0000-0000-0000-602f00000000}\Test\Foo.txt \\?\Volume{b75e2c83-0000-0000-0000-602f00000000}\Test\Foo.txt

Nota

La sintassi del percorso del dispositivo DOS è supportata nelle implementazioni .NET in esecuzione in Windows a partire da .NET Core 1.1 e .NET Framework 4.6.2.DOS device path syntax is supported on .NET implementations running on Windows starting with .NET Core 1.1 and .NET Framework 4.6.2.

Il percorso del dispositivo DOS è costituito dai componenti seguenti:The DOS device path consists of the following components:

  • L'identificatore del percorso del dispositivo (\\.\ o \\?\), che identifica il percorso come percorso di un dispositivo DOS.The device path specifier (\\.\ or \\?\), which identifies the path as a DOS device path.

    Nota

    \\?\ è supportato in tutte le versioni di .NET Core e in .NET Framework a partire dalla versione 4.6.2.The \\?\ is supported in all versions of .NET Core and in the .NET Framework starting with version 4.6.2.

  • Un collegamento simbolico all'oggetto dispositivo "reale" (C: nel caso di un nome di unità o Volume{b75e2c83-0000-0000-0000-602f00000000} nel caso di un GUID del volume).A symbolic link to the "real" device object (C: in the case of a drive name, or Volume{b75e2c83-0000-0000-0000-602f00000000} in the case of a volume GUID).

    Il primo segmento del percorso del dispositivo DOS dopo l'identificatore del percorso del dispositivo identifica il volume o l'unitàThe first segment of the DOS device path after the device path specifier identifies the volume or drive. (ad esempio, \\?\C:\ e \\.\BootPartition\).(For example, \\?\C:\ and \\.\BootPartition\.)

    È disponibile un collegamento specifico per i percorsi UNC, chiamato UNC.There is a specific link for UNCs that is called, not surprisingly, UNC. Ad esempio:For example:

    \\.\UNC\Server\Share\Test\Foo.txt \\?\UNC\Server\Share\Test\Foo.txt

    Per i percorsi UNC del dispositivo, la parte server/condivisione costituisce il volume.For device UNCs, the server/share portion forms the volume. Ad esempio, in \\?\server1\e:\utilities\\filecomparer\ la parte server/condivisione è server1\utilities.For example, in \\?\server1\e:\utilities\\filecomparer\, the server/share portion is server1\utilities. Ciò risulta particolarmente importante quando si chiama un metodo come Path.GetFullPath(String, String) con segmenti di directory relativi; non è mai possibile andare oltre il volume.This is significant when calling a method such as Path.GetFullPath(String, String) with relative directory segments; it is never possible to navigate past the volume.

I percorsi del dispositivo DOS sono completi per definizione.DOS device paths are fully qualified by definition. I segmenti di directory relativi (. e ..) non sono consentiti.Relative directory segments (. and ..) are not allowed. Le directory correnti non entrano mai in uso.Current directories never enter into their usage.

Esempio: modi per fare riferimento allo stesso fileExample: Ways to refer to the same file

L'esempio seguente illustra alcuni dei modi in cui è possibile fare riferimento a un file quando si usano le API nello spazio dei nomi System.IO.The following example illustrates some of the ways in which you can refer to a file when using the APIs in the System.IO namespace. L'esempio crea un'istanza di un oggetto FileInfo e usa le rispettive proprietà Name e Length per visualizzare il nome e la lunghezza del file.The example instantiates a FileInfo object and uses its Name and Length properties to display the filename and the length of the file.

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",
            @"\\127.0.0.1\c$\temp\test-file.txt" };

        foreach (var filename in filenames)
        {
            FileInfo fi = new FileInfo(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
//      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",
                "\\127.0.0.1\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

Normalizzazione del percorsoPath normalization

Quasi tutti i percorsi passati alle API di Windows sono normalizzati.Almost all paths passed to Windows APIs are normalized. Durante la normalizzazione, Windows esegue la procedura seguente:During normalization, Windows performs the following steps:

  • Identifica il percorso.Identifies the path.
  • Applica la directory corrente ai percorsi parzialmente completi (relativi).Applies the current directory to partially qualified (relative) paths.
  • Converte in forma canonica i separatori di directory e componenti.Canonicalizes component and directory separators.
  • Valuta i componenti di directory relativi (. per la directory corrente e .. per la directory padre).Evaluates relative directory components (. for the current directory and .. for the parent directory).
  • Elimina determinati caratteri.Trims certain characters.

Questa normalizzazione avviene in modo implicito, ma è possibile eseguirla in modo esplicito chiamando il metodo Path.GetFullPath, che esegue il wrapping di una chiamata alla funzione GetFullPathName().This normalization happens implicitly, but you can do it explicitly by calling the Path.GetFullPath method, which wraps a call to the GetFullPathName() function. È anche possibile chiamare la funzione GetFullPathName() di Windows direttamente tramite P/Invoke.You can also call the Windows GetFullPathName() function directly using P/Invoke.

Identificazione del percorsoIdentifying the path

Il primo passaggio nella normalizzazione del percorso consiste nell'identificare il tipo di percorso.The first step in path normalization is identifying the type of path. I percorsi rientrano in una delle categorie seguenti:Paths fall into one of a few categories:

  • Sono percorsi del dispositivo, vale a dire iniziano con due separatori e un punto interrogativo o un punto (\\? o \\.).They are device paths; that is, they begin with two separators and a question mark or period (\\? or \\.).
  • Sono percorsi UNC, vale a dire iniziano con due separatori senza un punto interrogativo o un punto.They are UNC paths; that is, they begin with two separators without a question mark or period.
  • Sono percorsi DOS completi, vale a dire iniziano con una lettera di unità, un separatore di volume e un separatore di componenti (C:\).They are fully qualified DOS paths; that is, they begin with a drive letter, a volume separator, and a component separator (C:\).
  • Definiscono un dispositivo legacy (CON, LPT1).They designate a legacy device (CON, LPT1).
  • Sono relativi alla radice dell'unità corrente, vale a dire iniziano con un separatore di componenti singolo (\).They are relative to the root of the current drive; that is, they begin with a single component separator (\).
  • Sono relativi alla directory corrente di un'unità specificata, vale a dire iniziano con una lettera di unità, un separatore di volume e nessun separatore di componenti (C:).They are relative to the current directory of a specified drive; that is, they begin with a drive letter, a volume separator, and no component separator (C:).
  • Sono relativi alla directory corrente, vale a dire iniziano con qualsiasi altro elemento (temp\testfile.txt).They are relative to the current directory; that is, they begin with anything else (temp\testfile.txt).

Il tipo di percorso determina se una directory corrente viene applicata o meno in qualche modo.The type of the path determines whether or not a current directory is applied in some way. Definisce inoltre qual è la "radice" del percorso.It also determines what the "root" of the path is.

Gestione dei dispositivi legacyHandling legacy devices

Se il percorso è un dispositivo DOS legacy come CON, COM1 o LPT1, viene convertito in un percorso del dispositivo anteponendo \\.\ e viene restituito.If the path is a legacy DOS device such as CON, COM1, or LPT1, it is converted into a device path by prepending \\.\ and returned.

Un percorso che inizia con il nome di un dispositivo legacy viene sempre interpretato come dispositivo legacy dal metodo Path.GetFullPath(String).A path that begins with a legacy device name is always interpreted as a legacy device by the Path.GetFullPath(String) method. Ad esempio, il percorso del dispositivo DOS per CON.TXT è \\.\CON e il percorso del dispositivo DOS per COM1.TXT\file1.txt è \\.\COM1.For example, the DOS device path for CON.TXT is \\.\CON, and the DOS device path for COM1.TXT\file1.txt is \\.\COM1.

Applicazione della directory correnteApplying the current directory

Se un percorso non è completo, Windows applica la directory corrente.If a path isn't fully qualified, Windows applies the current directory to it. I percorsi UNC e dei dispositivi non hanno la directory corrente applicataUNCs and device paths do not have the current directory applied. e neanche un'unità completa con il separatore C:\.Neither does a full drive with separator C:\.

Se il percorso inizia con un separatore di componenti singolo, viene applicata l'unità della directory corrente.If the path starts with a single component separator, the drive from the current directory is applied. Ad esempio, se il percorso del file è \utilities e la directory corrente è C:\temp\, la normalizzazione produce C:\utilities.For example, if the file path is \utilities and the current directory is C:\temp\, normalization produces C:\utilities.

Se il percorso inizia con una lettera di unità, un separatore di volume e nessun separatore di componenti, viene applicata l'ultima directory corrente impostata dalla shell dei comandi per l'unità specificata.If the path starts with a drive letter, volume separator, and no component separator, the last current directory set from the command shell for the specified drive is applied. Se l'ultima directory corrente non è stata impostata, viene applicata solo l'unità.If the last current directory was not set, the drive alone is applied. Ad esempio, se il percorso del file è D:sources, la directory corrente è C:\Documents\ e l'ultima directory corrente nell'unità D: è stata D:\sources\, il risultato è D:\sources\sources.For example, if the file path is D:sources, the current directory is C:\Documents\, and the last current directory on drive D: was D:\sources\, the result is D:\sources\sources. Questi percorsi "relativi di unità" sono una fonte comune di errori logici per script e programmi.These "drive relative" paths are a common source of program and script logic errors. Presupporre che un percorso che inizia con una lettera e i due punti non sia relativo ovviamente non è corretto.Assuming that a path beginning with a letter and a colon isn't relative is obviously not correct.

Se il percorso inizia con un elemento diverso da un separatore, vengono applicate l'unità e la directory correnti.If the path starts with something other than a separator, the current drive and current directory are applied. Ad esempio, se il percorso è filecompare e la directory corrente è C:\utilities\, il risultato è C:\utilities\filecompare\.For example, if the path is filecompare and the current directory is C:\utilities\, the result is C:\utilities\filecompare\.

Importante

I percorsi relativi sono pericolosi nelle applicazioni multithreading (vale a dire, la maggior parte delle applicazioni) perché la directory corrente è un'impostazione specifica per il processo.Relative paths are dangerous in multithreaded applications (that is, most applications) because the current directory is a per-process setting. Qualsiasi thread può modificare la directory corrente in qualsiasi momento.Any thread can change the current directory at any time. A partire da .NET Core 2.1, è possibile chiamare il metodo Path.GetFullPath(String, String) per ottenere un percorso assoluto da un percorso relativo e il percorso base (directory corrente) in base a cui si procede alla risoluzione.Starting with .NET Core 2.1, you can call the Path.GetFullPath(String, String) method to get an absolute path from a relative path and the base path (the current directory) that you want to resolve it against.

Conversione in forma canonica dei separatoriCanonicalizing separators

Tutte le barre (/) sono convertite nel separatore di Windows standard, la barra rovesciata (\).All forward slashes (/) are converted into the standard Windows separator, the back slash (\). Se sono presenti, una serie di barre che seguono le prime due vengono compresse in una singola barra.If they are present, a series of slashes that follow the first two slashes are collapsed into a single slash.

Valutazione dei componenti relativiEvaluating relative components

Mentre il percorso viene elaborato, vengono valutati tutti i componenti o i segmenti costituiti da un punto singolo o doppio (. o ..):As the path is processed, any components or segments that are composed of a single or a double period (. or ..) are evaluated:

  • Nel caso di un punto singolo, il segmento corrente viene rimosso, perché fa riferimento alla directory corrente.For a single period, the current segment is removed, since it refers to the current directory.

  • Nel caso di un punto doppio, il segmento corrente e quello padre vengono rimossi, perché il punto doppio fa riferimento alla directory padre.For a double period, the current segment and the parent segment are removed, since the double period refers to the parent directory.

    Le directory padre vengono rimosse solo se non sono oltre la radice del percorso.Parent directories are only removed if they aren't past the root of the path. La radice del percorso dipende dal tipo di percorso.The root of the path depends on the type of path. Si tratta dell'unità (C:\) per i percorsi DOS, del server/condivisione per i percorsi UNC (\\Server\Share) e del prefisso del percorso del dispositivo per i percorsi del dispositivo (\\?\ o \\.\).It is the drive (C:\) for DOS paths, the server/share for UNCs (\\Server\Share), and the device path prefix for device paths (\\?\ or \\.\).

Eliminazione di caratteriTrimming characters

Insieme ai separatori e ai segmenti relativi rimossi in precedenza, durante la normalizzazione vengono rimossi alcuni caratteri aggiuntivi:Along with the runs of separators and relative segments removed earlier, some additional characters are removed during normalization:

  • Se un segmento termina con un punto singolo, il punto viene rimossoIf a segment ends in a single period, that period is removed. (un segmento di un punto singolo o doppio è normalizzato nel passaggio precedente;(A segment of a single or double period is normalized in the previous step. un segmento di tre o più punti non è normalizzato ed è in realtà un nome di file/directory valido).A segment of three or more periods is not normalized and is actually a valid file/directory name.)

  • Se il percorso non termina con un separatore, tutti gli spazi e i punti finali (U+0020) vengono rimossi.If the path doesn't end in a separator, all trailing periods and spaces (U+0020) are removed. Se l'ultimo segmento è semplicemente un punto singolo o doppio, rientra nella regola dei componenti relativi esposta in precedenza.If the last segment is simply a single or double period, it falls under the relative components rule above.

    Questa regola indica che è possibile creare un nome di directory con uno spazio finale mediante l'aggiunta di un separatore finale dopo lo spazio.This rule means that you can create a directory name with a trailing space by adding a trailing separator after the space.

    Importante

    Non creare mai una directory o un nome file con uno spazio finale.You should never create a directory or filename with a trailing space. Gli spazi finali possono rendere difficile o impossibile l'accesso a una directory e le applicazioni riscontrano in genere un errore quando si tenta di gestire directory o file i cui nomi includono spazi finali.Trailing spaces can make it difficult or impossible to access a directory, and applications commonly fail when attempting to handle directories or files whose names include trailing spaces.

Esclusione della normalizzazioneSkipping normalization

Normalmente, qualsiasi percorso passato a un'API di Windows viene effettivamente passato alla funzione GetFullPathName e normalizzato.Normally, any path passed to a Windows API is (effectively) passed to the GetFullPathName function and normalized. Un'eccezione degna di nota è quando il percorso di un dispositivo inizia con un punto interrogativo anziché con un punto.There is one important exception: a device path that begins with a question mark instead of a period. A meno che il percorso non inizi esattamente con \\?\ (si noti l'uso della barra rovesciata canonica), viene normalizzato.Unless the path starts exactly with \\?\ (note the use of the canonical backslash), it is normalized.

Perché escludere la normalizzazione?Why would you want to skip normalization? Per tre motivi principali:There are three major reasons:

  1. Per ottenere l'accesso a percorsi che non sono in genere disponibili ma sono validi.To get access to paths that are normally unavailable but are legal. A un file o una directory denominata hidden., ad esempio, è impossibile accedere in qualsiasi altro modo.A file or directory called hidden., for example, is impossible to access in any other way.

  2. Per migliorare le prestazioni escludendo la normalizzazione se è già stata eseguita.To improve performance by skipping normalization if you've already normalized.

  3. Solo in .NET Framework, per ignorare il controllo MAX_PATH per la lunghezza del percorso in modo da consentire percorsi contenenti più di 259 caratteri.On the .NET Framework only, to skip the MAX_PATH check for path length to allow for paths that are greater than 259 characters. La maggior parte delle API consente questa operazione, con alcune eccezioni.Most APIs allow this, with some exceptions.

Nota

.NET Core gestisce i percorsi lunghi in modo implicito e non esegue un controllo MAX_PATH..NET Core handles long paths implicitly and does not perform a MAX_PATH check. Il controllo MAX_PATH si applica solo a .NET Framework.The MAX_PATH check applies only to the .NET Framework.

L'esclusione della normalizzazione e dei controlli MAX_PATH è l'unica differenza tra le sintassi dei due percorsi di dispositivo; altrimenti sono identici.Skipping normalization and max path checks is the only difference between the two device path syntaxes; they are otherwise identical. Prestare attenzione quando si esclude la normalizzazione, perché si rischia di creare percorsi difficili da gestire con le "normali" applicazioni.Be careful with skipping normalization, since you can easily create paths that are difficult for "normal" applications to deal with.

I percorsi che iniziano con \\?\ vengono comunque normalizzati se si passano in modo esplicito alla funzione GetFullPathName.Paths that start with \\?\ are still normalized if you explicitly pass them to the GetFullPathName function.

È possibile passare i percorsi di più di MAX_PATH caratteri a GetFullPathName senza \\?\ .You can pass paths of more than MAX_PATH characters to GetFullPathName without \\?\. Supporta percorsi di lunghezza arbitraria fino alla dimensione massima delle stringhe che Windows è in grado di gestire.It supports arbitrary length paths up to the maximum string size that Windows can handle.

Maiuscole/minuscole e file system di WindowsCase and the Windows file system

Una peculiarità del file system di Windows che può confondere gli utenti e gli sviluppatori non Windows è che i nomi di percorsi e directory non fanno distinzione tra maiuscole e minuscole.A peculiarity of the Windows file system that non-Windows users and developers find confusing is that path and directory names are case-insensitive. In altre parole, i nomi di file e directory riflettono l'uso di maiuscole/minuscole delle stringhe usate quando sono stati creati.That is, directory and file names reflect the casing of the strings used when they are created. Ad esempio, la chiamata al metodoFor example, the method call

Directory.Create("TeStDiReCtOrY");
Directory.Create("TeStDiReCtOrY")

crea una directory denominata TeStDiReCtOrY.creates a directory named TeStDiReCtOrY. Se si rinomina una directory o un file per modificare l'uso di maiuscole/minuscole, il nome del file o della directory riflette le maiuscole/minuscole usate quando è stato rinominato.If you rename a directory or file to change its case, the directory or file name reflects the case of the string used when you rename it. Ad esempio, il codice seguente rinomina un file denominato test.txt in Test.txt:For example, the following code renames a file named test.txt to Test.txt:

using System.IO;

class Example
{
   static void Main()
   {
      var fi = new FileInfo(@".\test.txt");
      fi.MoveTo(@".\Test.txt");
   }
}
Imports System.IO

Module Example
    Public Sub Main()
        Dim fi As New FileInfo(".\test.txt")
        fi.MoveTo(".\Test.txt")
    End Sub
End Module

Tuttavia, nei confronti tra i nomi di file e directory non viene fatta distinzione tra maiuscole e minuscole.However, directory and file name comparisons are case-insensitive. Se si cerca un file denominato "test.txt", le API del file system .NET non fanno distinzione tra maiuscole e minuscole nel confronto.If you search for a file named "test.txt", .NET file system APIs ignore case in the comparison. Test.txt, TEST.TXT, test.TXT e qualsiasi altra combinazione di lettere maiuscole e minuscole corrisponderanno a "test.txt".Test.txt, TEST.TXT, test.TXT, and any other combination of upper- and lowercase letters will match "test.txt".