2009-11-29 20 views
9

Si tengo una cadena que se resuelve en una ruta de archivo en Windows, ¿hay alguna forma aceptada de obtener una forma canónica del nombre de archivo?¿Cómo puedo resolver un nombre de archivo canónico en Windows?

Por ejemplo, me gustaría saber si

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

y

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

realidad apuntan al mismo archivo o no, y almacenar la forma canónica de la ruta en mi solicitud.

Tenga en cuenta que las comparaciones simples de cadenas no funcionarán, ni tampoco ninguna magia RegEx. Recuerde que tenemos cosas como NTFS reparse points para hacer frente desde Windows 2000 y la nueva estructura de Bibliotecas en Windows 7.

+0

y el buen viejo 'subst' también. – EFraim

+0

¿Qué idioma/marco estás usando? – jheddings

+0

También puede intentar preguntar sobre esto en serverfault.com o superuser.com – DOK

Respuesta

8

Respuesta corta: realmente no.

No hay una forma simple de obtener el nombre canónico de un archivo en Windows. Los archivos locales pueden estar disponibles a través de puntos de reanálisis, a través de SUBST. ¿Quieres lidiar con uniones NTFS? ¿Atajos de Windows? ¿Qué pasa con \\?\ -signos de archivos protegidos

Los archivos remotos pueden estar disponibles mediante una letra de unidad asignada o mediante UNC. ¿Ese es el UNC al servidor de origen? ¿Estás usando DFS? ¿El servidor está usando puntos de análisis, etc.? ¿El servidor está disponible por más de un nombre? ¿Qué pasa con la dirección IP? ¿Tiene más de una dirección IP?

Por lo tanto, si está buscando algo así como el número de inodo en Windows, no está allí. Ver, por ejemplo, this page.

+0

+1 para el enlace a la publicación agradable del blog 'PathCanonicalize Versus What Itss On The Tin' –

+3

Wow. Que desastre. ¿Por qué no es nada fácil en Windowsland? – dthrasher

+0

-1: [GetFileInformationByHandle] (http://msdn.microsoft.com/en-us/library/aa364952%28VS.85%29.aspx) es * exactamente * el "algo así como el número de inodo" que dices ain no hay Está ahí bien. –

3

Usando FileInfo (ejemplo en 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); 

de salida es:

sí, son iguales
C: \ cosas \ cosas \ etc \ misc \ whatever.txt
C: \ cosas \ cosas \ etc \ misc \ whatever.txt

+0

No estoy seguro de que la comprobación Equals sea útil; hasta donde puedo decir, FileInfo no anula Equals, por lo que esto solo le dará igualdad de referencia, no equivalencia de ruta de archivo. Por lo tanto, en su ejemplo, info1.Equals (info2) devuelve falso. – itowlson

+0

@itowlson: sí, me di cuenta también de que después de leer los documentos ... Cambié mi respuesta y realmente lo probé esta vez :) – jheddings

+0

No es una solución completa, como lo señaló @Roger Lipscombe en su respuesta. Podríamos tener que invocar la regla 80/20 en este caso. – dthrasher

1

jheddings tiene una respuesta agradable, pero ya que no indicó en qué idioma está utilizando, yo pensé que le daría una manera de hacerlo Python que también trabaja desde la línea de comandos, utilizando 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 es correcto, no hay una manera simple. Si el volumen admite el archivo de un índice de archivo único, puede abrir el archivo y llamar al GetFileInformationByHandle, pero esto no funcionará en todos los volúmenes.

La llamada API de Windows GetFullPathName puede ser el mejor enfoque simple.

+0

+1 ... también el índice del archivo es único w.r.t. el volumen, por lo que también necesita el número de serie del volumen, suponiendo que esté disponible de forma remota. –

+0

Buen punto de aclaración, gracias Roger. –

0

Usaría System.IO.Path.GetFullPath. Toma una cadena como entrada (C: \ cosas \ cosas \ etc \ misc \ other ... \ whatever.txt en su caso) y generará una cadena (C: \ cosas \ cosas \ etc \ misc \ whatever.txt)

-1

Para obtener la ruta canónica, debe usar la función PathCanonicalize.

+0

No, la función no calcula una ruta canónica a pesar de su nombre. Consulte la sección "Observaciones" de su documentación: la función solo hace correcciones de cadena simples. P.ej. para ".. \ someFile.txt" devolverá "someFile.txt" cuando los programadores esperan algo como "C: \ someDir \ someFile.txt" como una ruta canónica. –

0

Supongo que es un poco tarde, pero puede usar System.IO.Path.GetFullPath ("C: \ cosas \ cosas \ etc \ misc \ other .. \ whatever.txt") y devolverá "C: \ cosas \ cosas \ etc \ misc \ whatever.txt"

Cuestiones relacionadas