2009-11-29 12 views
9

Se ho una stringa che si risolve in un percorso file in Windows, esiste un modo accettato per ottenere una forma canonica del nome del file?Come posso risolvere un nome file canonico in Windows?

Per esempio, mi piacerebbe sapere se

C:\stuff\things\etc\misc\whatever.txt 

e

C:\stuff\things\etc\misc\other\..\whatever.txt 

in realtà puntano allo stesso file o meno, e conservare la forma canonica del percorso nella mia applicazione.

Si noti che i confronti tra stringhe semplici non funzioneranno, e nemmeno le magie RegEx. Ricordate che abbiamo cose come NTFS reparse points da affrontare a partire da Windows 2000 e la nuova struttura di biblioteche in Windows 7.

+0

e il buon vecchio 'subst' pure. – EFraim

+0

Che lingua/struttura stai usando? – jheddings

+0

Si potrebbe anche provare a chiedere su questo serverfault.com o superuser.com – DOK

risposta

8

Risposta breve: non proprio.

Non esiste un modo semplice per ottenere il nome canonico di un file su Windows. I file locali possono essere disponibili tramite punti di analisi, tramite SUBST. Vuoi occuparti delle giunzioni NTFS? Scorciatoie di Windows? Che dire di nomi di file \\?\ -escaped

I file remoti possono essere disponibili tramite la lettera di unità mappata o tramite UNC. È l'UNC al server di origine? Stai usando DFS? Il server utilizza punti di analisi, ecc.? Il server è disponibile con più di un nome? E l'indirizzo IP? Ha più di un indirizzo IP?

Quindi, se stai cercando qualcosa come il numero di inode su Windows, non è lì. Vedi, ad esempio, this page.

+0

+1 per il link al post del blog piacevole 'PathCanonicalize Versus What It Says On The Tin' –

+3

Wow. Che casino. Perché niente è facile in Windowsland? – dthrasher

+0

-1: [GetFileInformationByHandle] (http://msdn.microsoft.com/en-us/library/aa364952%28VS.85%29.aspx) è * esattamente * il "qualcosa come il numero di inode" che si dice ain ci sono. Va tutto bene. –

3

Utilizzando FileInfo (ad esempio in C#):

FileInfo info1 = new FileInfo(@"C:\stuff\things\etc\misc\whatever.txt"); 
FileInfo info2 = new FileInfo(@"C:\stuff\things\etc\misc\other\..\whatever.txt"); 
if (info1.FullName.Equals(info2.FullName)) { 
    Console.WriteLine("yep, they're equal"); 
} 
Console.WriteLine(info1.FullName); 
Console.WriteLine(info2.FullName); 

uscita è:

Sì, sono uguali
C: \ roba \ cose \ etc \ Misc \ whatever.txt
C: \ roba \ cose \ etc \ Misc \ whatever.txt

+0

Non sono sicuro che il controllo di uguale sarà utile, per quanto posso dire che FileInfo non ha la precedenza su Equals, quindi questo ti darà solo l'uguaglianza di riferimento, non l'equivalenza del percorso del file. Pertanto, nel tuo esempio, info1.Equals (info2) restituisce false. – itowlson

+0

@itowlson: sì, ho notato anche che dopo aver letto i documenti ... ho cambiato la mia risposta e in realtà questa volta l'ho testata :) – jheddings

+0

Non è una soluzione completa, come ha sottolineato @Roger Lipscombe nella sua risposta. Potremmo dover invocare la regola 80/20 su questo. – dthrasher

1

jheddings ha una bella risposta, ma dal momento che non ha indicato quale lingua si sta utilizzando, io ho pensato di dare un senso di Python per farlo che funziona anche da linea di comando, utilizzando os.path.abspath:

> python -c "import os.path; print os.path.abspath('C:\stuff\things\etc\misc\other\..\whatever.txt')" 
C:\stuff\things\etc\misc\whatever.txt 
4

Roger è corretto, non esiste un modo semplice. Se il volume supporta un indice di file univoco, è possibile aprire il file e chiamare GetFileInformationByHandle, ma questo non funzionerà su tutti i volumi.

La chiamata API Windows GetFullPathName può essere l'approccio migliore.

+0

+1 ... anche l'indice del file è solo univoco w.r.t. il volume, quindi è necessario anche il numero di serie del volume, presupponendo che sia disponibile in remoto. –

+0

Buon punto di chiarimento, grazie Roger. –

0

Vorrei utilizzare System.IO.Path.GetFullPath. Prende una stringa come input (C: \ stuff \ things \ etc \ misc \ other .. \ whatever.txt nel tuo caso) e genererà una stringa (C: \ stuff \ things \ etc \ misc \ whatever.txt).

-1

Per ottenere il percorso canonico è necessario utilizzare la funzione PathCanonicalize.

+0

No, la funzione non calcola un percorso canonico nonostante il suo nome. Vedi la sezione "Note" della sua documentazione: la funzione esegue solo semplici correzioni di stringhe. Per esempio. per ".. \ someFile.txt" restituirà "someFile.txt" quando i programmatori si aspettano qualcosa come "C: \ someDir \ someFile.txt" come percorso canonico. –

0

Suppongo di essere un po 'in ritardo, ma è possibile utilizzare System.IO.Path.GetFullPath ("C: \ stuff \ things \ etc \ misc \ other .. \ whatever.txt") e verrà restituito "C: \ stuff \ things \ etc \ misc \ whatever.txt"

Problemi correlati