2009-11-29 11 views
9

Jeśli mam ciąg znaków, który rozwiązuje ścieżkę pliku w systemie Windows, czy istnieje akceptowany sposób uzyskania kanonicznej postaci nazwy pliku?Jak mogę rozwiązać kanoniczną nazwę pliku w systemie Windows?

Na przykład, chciałbym wiedzieć, czy

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

i

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

rzeczywiście wskazują na ten sam plik lub nie, i przechowywać kanoniczną formę ścieżki w mojej aplikacji.

Należy pamiętać, że proste porównywanie ciągów nie zadziała, podobnie jak żadna magia RegEx. Pamiętaj, że mamy takie rzeczy jak NTFS reparse points do czynienia z od Windows 2000 i nowej struktury Biblioteki w Windows 7.

+0

i dobre stare 'subst' również. – EFraim

+0

Jakiego języka/architektury używasz? – jheddings

+0

Możesz również spróbować zapytać o to na serverfault.com lub superuser.com – DOK

Odpowiedz

8

Krótka odpowiedź: niezupełnie.

Nie ma prostego sposobu na uzyskanie kanonicznej nazwy pliku w systemie Windows. Pliki lokalne mogą być dostępne poprzez punkty ponownej analizy za pośrednictwem SUBST. Czy chcesz zajmować się połączeniami NTFS? Skróty Windows? A co z \\?\ -enaped nazw plików

Pliki zdalne mogą być dostępne poprzez zmapowaną literę dysku lub przez UNC. Czy to UNC do serwera pochodzenia? Czy korzystasz z DFS? Czy serwer korzysta z punktów ponownej analizy itp.? Czy serwer jest dostępny przez więcej niż jedną nazwę? A co z adresem IP? Czy ma więcej niż jeden adres IP?

Tak więc, jeśli szukasz czegoś takiego, jak numer i-węzła w systemie Windows, to go nie ma. Zobacz na przykład this page.

+0

+1 za link do ładnego wpisu na blogu "PathCanonicalize Versus What It Says On The Tin" –

+3

Wow. Co za bałagan. Dlaczego w Windowsland nie ma nic prostszego? – dthrasher

+0

-1: [GetFileInformationByHandle] (http://msdn.microsoft.com/en-us/library/aa364952%28VS.85%29.aspx) jest * dokładnie * "czymś w rodzaju liczby i-węzła", o którym mówisz tam jest. Jest tam w porządku. –

3

Korzystanie FileInfo (przykład w języku 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); 

wyjście jest:

Tak, są równe
C: \ rzeczy \ rzeczy \ etc \ misc \ whatever.txt
C: \ rzeczy \ rzeczy \ etc \ misc \ whatever.txt

+0

Nie jestem pewien, czy sprawdzanie równości okaże się przydatne - o ile mogę powiedzieć, FileInfo nie przesłania Equali, więc to da ci równość referencyjną, a nie ekwiwalencję ścieżki pliku. Zatem w twoim przykładzie info1.Equals (info2) zwraca wartość false. – itowlson

+0

@itowlson: tak, zauważyłem też, że po przeczytaniu dokumentów ... zmieniłem moją odpowiedź i faktycznie przetestowałem ją tym razem :) – jheddings

+0

To nie jest kompletne rozwiązanie, jak zauważył w swojej odpowiedzi @Roger Lipscombe. Być może będziemy musieli odwołać się do reguły 80/20 w tej sprawie. – dthrasher

1

jheddings ma ładny odpowiedź, ale ponieważ nie wskazuje język, którego używasz, myślałem dałbym sposób Pythona, aby to zrobić, że działa również z wiersza poleceń, używając 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 ma rację, nie ma prostego sposobu. Jeśli wolumin obsługuje plik unikalny indeks pliku, można otworzyć plik i zadzwonić pod numer GetFileInformationByHandle, ale nie będzie działać na wszystkich woluminach.

Wywołanie funkcji API systemu Windows GetFullPathName może być najlepszym prostym podejściem.

+0

+1 ... także indeks pliku jest tylko unikalny w.r.t. wolumin, więc potrzebujesz również numeru seryjnego woluminu, zakładając, że jest on dostępny zdalnie. –

+0

Dobra rada, dzięki Roger. –

0

Chciałbym użyć System.IO.Path.GetFullPath. Bierze ciąg znaków jako dane wejściowe (C: \ stuff \ things \ etc \ misc \ other .. \ whatever.txt w twoim przypadku) i wypisze ciąg znaków (C: \ stuff \ things \ etc \ misc \ whatever.txt).

-1

Aby uzyskać ścieżkę kanoniczną, należy użyć funkcji PathCanonicalize.

+0

Nie, funkcja nie oblicza kanonicznej ścieżki pomimo swojej nazwy. Zobacz sekcję "Uwagi" w jej dokumentacji: funkcja wykonuje tylko proste korekty ciągów. Na przykład. dla ".. \ someFile.txt" zwróci "someFile.txt", gdy programiści oczekują czegoś w stylu "C: \ someDir \ someFile.txt" jako ścieżki kanonicznej. –

0

Chyba jestem trochę spóźniony, ale możesz użyć System.IO.Path.GetFullPath ("C: \ stuff \ things \ etc \ misc \ other .. \ whatever.txt") i to się zwróci "C: \ rzeczy \ rzeczy \ etc \ misc \ whatever.txt"

Powiązane problemy