Scrivere un percorso come C:\Users\Nome\Documents su Windows e /home/nome/Documents su Linux sembra una differenza marginale, quasi cosmetica. In realtà, dietro una diversa modalità di esprimere i percorsi si nascondono due modi differenti di rappresentare file, directory e unità di memorizzazione, maturati in epoche differenti e soprattutto sotto vincoli del tutto difformi.
Windows conserva ancora oggi due elementi che risalgono direttamente alla storia di DOS: la lettera dell’unità, come C:, e il backslash \ come separatore tra le directory. Linux e gli altri sistemi Unix-like seguono invece il modello Unix: un unico albero gerarchico che parte dalla radice /, senza bisogno di identificare ogni unità con una lettera. In un altro articolo abbiamo spiegato perché il file system Linux confonde gli utenti Windows.
La parte interessante è che questa differenza non nasce da una scelta progettuale compiuta quando Windows era già Windows. Per comprenderla bisogna tornare ai primi anni ’80, quando MS-DOS non aveva ancora neppure il concetto di directory come lo intendiamo oggi.
Prima di C:\ c’erano A: e B:
Le lettere delle unità sono più vecchie sia di Windows sia del disco fisso nei PC IBM. I primi sistemi DOS erano pensati principalmente per lavorare con floppy disk: il primo drive era identificato come A:, l’eventuale secondo come B:; il modello proveniva dall’ambiente CP/M e risultava perfettamente sensato su macchine che potevano avere uno o due lettori di dischetti ma nessun disco fisso.
La prima versione di PC-DOS, distribuita con l’IBM PC nel 1981, manteneva una struttura del file system sostanzialmente piatta: esisteva la directory principale del disco, ma l’utente non poteva costruire alberi di directory e sottodirectory come facciamo oggi.
Indicare qualcosa come A:LETTERA.TXT era sufficiente per stabilire sia su quale supporto cercare il file, sia quale file aprire.
Quando i dischi fissi iniziarono a diventare una componente “abituale” dei PC, le prime due lettere erano ormai occupate per tradizione dai floppy. Il disco fisso prese quindi la successiva C: ed è proprio da qui che è scaturita la convenzione sopravvissuta per oltre quarant’anni.
Ancora oggi Microsoft definisce un normale percorso Windows completamente qualificato come una combinazione di lettera dell’unità, due punti, backslash e componenti del percorso: per esempio C:\Directory\File.txt. La documentazione Win32 continua inoltre a supportare percorsi UNC come \\server\share\file e percorsi che identificano direttamente un volume tramite GUID (Globally Unique Identifier), a dimostrazione del fatto che C: è ormai soprattutto uno dei diversi modi attraverso i quali Windows presenta un volume alle applicazioni.
MS-DOS 2.0 cambia tutto: arrivano le directory
Il passaggio fondamentale avvenne con MS-DOS 2.0 (1983), sviluppato per accompagnare l’IBM PC XT e il suo disco fisso.
Nemanja Trifunovic ricostruisce bene questo momento nel suo approfondimento “The Road to MS-DOS 2“. IBM avrebbe voluto soprattutto un DOS capace di gestire il nuovo hard disk senza aumentare troppo il consumo di memoria; Paul Allen e alcuni sviluppatori Microsoft colsero invece l’occasione per ripensare parti importanti del sistema.
La modifica più evidente riguardava proprio il file system: DOS 1.x utilizzava una struttura adatta ai floppy, mentre per un disco da diversi megabyte diventava sempre meno ragionevole accumulare centinaia o migliaia di file tutti nello stesso livello.
MS-DOS 2.0 introdusse quindi una struttura gerarchica con directory principale e sottodirectory, fortemente ispirata al modello Unix/XENIX. L’articolo di Trifunovic sottolinea come quella versione introdusse anche altri concetti derivati o influenzati da XENIX: file handle, redirezione dell’I/O, driver caricabili e utilità come find, more e sort.
Microsoft ha pubblicato su GitHub il codice sorgente originale di MS-DOS 1.25 e 2.0: nella directory della versione 2.0 compaiono persino file chiamati XENIX.ASM e XENIX2.ASM, testimonianza piuttosto esplicita di quella contaminazione tecnica. Il file README.txt, tra l’altro, documentava esplicitamente una modifica dell’ultimo minuto per aumentare la compatibilità con PC-DOS: l’uso di \ al posto di / come separatore dei percorsi e di / al posto di – come carattere per gli switch dei comandi!
Unix aveva già scelto lo slash /
Unix aveva affrontato il problema anni prima: nel modello Unix esiste infatti un’unica directory radice, indicata con /. Tutto il resto discende da essa:
/home
/home/mario
/home/mario/documenti
La specifica POSIX conserva ancora oggi questo principio: un pathname è costituito da nomi separati mediante il carattere /; un percorso formato dal solo slash identifica la directory radice del processo.
Introducendo le directory gerarchiche in DOS 2.0, Microsoft prese in considerazione uno schema come C:/DOS/COMMAND.COM; il problema era che / aveva già un altro significato nel mondo DOS. MS-DOS 1.x utilizzava lo slash per indicare le opzioni (o switch) dei comandi ed è una convenzione che esiste ancora. Si pensi ai seguenti:
dir /w
format /q
xcopy /s
La scelta derivava dalla tradizione di precedenti sistemi DEC (computer e sistemi operativi prodotti da Digital Equipment Corporation, una delle aziende più importanti dell’informatica dagli anni ’60 agli anni ’90) e risultava già radicata prima che DOS disponesse delle sottodirectory. La MS-DOS Encyclopedia, pubblicata da Microsoft Press, documenta esplicitamente la decisione: XENIX (versione commerciale di Unix sviluppata da Microsoft a partire dalla fine degli anni ’70 e poi distribuita anche tramite partner come SCO) usava lo slash come separatore, ma DOS 1.x utilizzava già / per gli switch della riga di comando; Microsoft, su richiesta IBM, adottò quindi il backslash \ per separare directory e file.
C:\ non significa esattamente “la radice di Windows”
Un altro aspetto interessante è che C:\, se ci pensate, non equivale concettualmente alla / di Linux. È invece la directory radice del volume associato alla lettera C. Windows può infatti avere contemporaneamente C:\, D:\, E:\ e così via, ciascuno con una propria radice.
Linux presenta invece al software un unico albero di directory /. Un secondo disco non deve assumere alcuna identità indipendente: può essere montato, per esempio, in /mnt/dati oppure /home o praticamente in qualunque altro punto appropriato (si parla di mount point). Da quel momento il contenuto del nuovo filesystem appare come un ramo dello stesso albero.
Anche Windows sa fare qualcosa di simile ai mount point Linux: come accennato in precedenza, infatti, le lettere identificative di unità non sono l’unico modello disponibile in Windows moderno. NTFS e Windows possono montare un volume anche all’interno di una directory di un altro volume. Per esempio, un secondo disco potrebbe apparire come C:\Dati\Archivio, senza possedere necessariamente una lettera propria.
Windows identifica inoltre internamente i volumi mediante nomi come \\?\Volume{GUID}\ tanto che la documentazione Microsoft mostra espressamente che un volume può essere raggiunto tramite il suo Volume GUID, indipendentemente dalla tradizionale lettera C: o D:.
Provate ad esempio a digitare mountvol C:\ /L per ottenere il Volume GUID corrispondente all’unità C: in Windows. Ancora meglio, provate a digitare quanto segue in una finestra PowerShell:
Get-CimInstance Win32_Volume |
Select-Object DriveLetter, Label, DeviceID
Perché Windows accetta talvolta anche lo slash /
Provando alcune API o programmi Windows si scopre che spesso supportano anche la forma C:/Users/Mario/Documents, che non prevede l’uso del backslash.
Microsoft continua a definire \ come separatore standard, ma diversi livelli software normalizzano lo slash trasformandolo in backslash. La documentazione .NET, per esempio, specifica che su Windows gli slash / possono essere convertiti nel separatore standard \ durante la canonicalizzazione del percorso.
Per questo motivo, la forma C:/temp/file.txt può funzionare perfettamente in numerosi programmi ma non bisogna dedurne che le due forme siano sempre intercambiabili.
Il problema emerge soprattutto nella riga di comando, dove / può indicare un’opzione e dove ogni programma è libero di interpretare gli argomenti secondo le proprie regole.
PowerShell è molto più tollerante del vecchio cmd.exe: comandi come Get-ChildItem C:/Windows/System32 funzionano normalmente.
In PowerShell è inoltre integrato un modello nel quale la sintassi simile a quella dei percorsi non viene utilizzata soltanto per file e directory. Ad esempio, HKLM:\Software\Microsoft rappresenta un percorso nel Registro di sistema, non nel filesystem.
Perché Windows usa anche il doppio backslash \\
Il backslash singolo \ separa normalmente i componenti di un percorso Windows; quando però un percorso inizia con due backslash, il significato cambia. La forma più comune è quella dei percorsi UNC (Universal Naming Convention), utilizzati per raggiungere una risorsa condivisa in rete senza assegnarle una lettera di unità:
\\SERVER\Condivisione\Cartella\File.txt
SERVER identifica il computer, il server o il NAS remoto, mentre Condivisione è il nome della risorsa pubblicata in rete. Un percorso UNC permette quindi di accedere direttamente alla condivisione; Windows può eventualmente associarle anche una lettera, per esempio trasformando \\NAS\Documenti nell’unità Z:, ma si tratta soltanto di un’ulteriore modalità di accesso alla stessa risorsa.
Percorsi speciali, condivisioni SMB e linguaggi di programmazione
Windows usa il doppio backslash anche in alcuni percorsi speciali del namespace Win32. Sequenze come \\?\C:\Percorso\File.txt oppure \\?\Volume{GUID}\ non identificano una condivisione di rete: \\?\ è un prefisso speciale utilizzato dalle API Windows per passare il percorso al sistema con meno elaborazioni e normalizzazioni automatiche. È proprio questa sintassi che permette, tra le altre cose, di riferirsi direttamente a un volume attraverso il suo identificatore anziché tramite una tradizionale lettera come C: o D:.
Un terzo caso compare nei linguaggi di programmazione. Poiché in molte stringhe \ svolge la funzione di carattere di escape, il percorso reale C:\Windows\Temp può dover essere scritto nel codice come C:\\Windows\\Temp. In questa situazione i due backslash non appartengono al percorso: rappresentano semplicemente un unico \.
Su Linux e più in generale nei sistemi Unix-like non esiste un equivalente diretto del prefisso UNC \\. Una condivisione di rete è normalmente montata all’interno dell’unico albero del filesystem, per esempio in /mnt/nas, diventando poi accessibile come /mnt/nas/documenti/file.txt.
È comunque possibile incontrare forme come //SERVER/Condivisione quando si utilizzano strumenti SMB/CIFS, ad esempio con mount -t cifs: in quel caso si tratta della sintassi con cui il programma identifica la risorsa SMB, non di un particolare tipo di pathname Linux paragonabile agli UNC di Windows.
Anche questa differenza riflette i due modelli di fondo: Windows conserva nomi specifici per unità e risorse di rete, mentre Unix tende a ricondurre filesystem locali e remoti all’interno dello stesso albero che parte da /.