2009-03-26 13 views

Respuesta

4

Dependiendo de si las rutas pueden ser relativas, o contener "..", o puntos de unión, o rutas UNC esto puede ser más difícil de lo que piensas. La mejor manera podría ser utilizar la función GetFileInformationByHandle() como en this answer.

Edit: Estoy de acuerdo con el comentario de RBerteig de que esto puede ser difícil o imposible de hacer si las rutas no apuntan a un archivo local. Cualquier comentario sobre cómo manejar de forma segura este caso sería muy apreciado.

+0

Mientras las dos rutas se resuelvan en archivos en la misma computadora, parece que GetFileInformationByHandle() es la respuesta correcta.Si se resuelven en diferentes computadoras, no veo una garantía, y tampoco veo una manera trivial de obtener una. No es necesariamente fácil probar esto. – RBerteig

+0

Todos los archivos son locales en mi caso, así que esto funciona. –

+0

@RBerteig: tampoco veo una forma trivial de obtener uno. Pero encontré uno muy no trivial y lo puse en una respuesta; echar un vistazo. Incluso ese solo es casi infalible, pero debería ser más que suficiente para la mayoría de las personas. – steveha

3

Hay casos extraños. Por ejemplo, "c: \ windows ... \ data \ myfile.txt" es lo mismo que "c: \ data. \ Myfile.txt" y "c: \ data \ myfile.txt". Puede tener cualquier número de "\. \" Y "\ ... \" allí. Puede consultar la función API de Windows GetFullPathName. Podría hacer canonicalización para ti.

6

Puedo sugerir PathCanonicalize?

+0

No parece que se dirija ni a los puntos de unión ni a las rutas UNC ... pero parece útil conocerlo. – RBerteig

+0

Ese es el método que estaba buscando. No GetFullPathName. –

+6

Después de ver esta respuesta, traté de utilizar PathCanonicalize() y descubrí que está terriblemente roto. 'PathCanonicalize (" ../ foo.txt ")' siempre devuelve '/ foo.txt'! PathCanonicalize() solo hace una edición trivial en la cadena, y el comportamiento de ruptura anterior es documentado. Inútil. Voy a publicar otra respuesta con lo que encontré. – steveha

6

Encontré una entrada de blog con la función más completa, incluso elaborada, que he visto para resolver este problema. Maneja cualquier cosa, incluso casos de esquinas horribles como V:foo.txt donde usaste el comando subst para mapear V: a Z: pero ya usaste subst para asignar Z: a alguna otra unidad; gira hasta que se desenrollan todos los comandos subst. URL:

http://pdh11.blogspot.com/2009/05/pathcanonicalize-versus-what-it-says-on.html

Mi proyecto es el código C puro, y que la función es C++. Empecé a traducirlo, pero luego descubrí que podía obtener la ruta normalizada que quería con una llamada a la función: GetLongPathName(). Esto no manejará los horribles casos de esquina, pero manejó mis necesidades inmediatas.

descubrí que GetLongPathName("foo.txt") sólo devuelve foo.txt, pero sólo anteponiendo ./ al nombre de archivo que tiene la expansión de forma normalizada:

GetLongPathName("./foo.txt"), si se ejecuta en el directorio C:\Users\steveha, devuelve C:\Users\steveha\foo.txt.

Así, en pseudocódigo:

si el segundo carácter del nombre de ruta se ':' o el primer carácter sea '/' o '\', simplemente llame GetLongPathName() otra cosa, copiar "./" a un búfer temporal, luego copie el nombre de archivo al búfer temporal + 2, para obtener una copia del nombre de archivo junto con "./" y luego llame a GetLongPathName().

+0

Bueno, al menos esa publicación proporciona un código que parece que hace todo el trabajo pesado. Ciertamente maneja más casos de esquina y más completamente de lo que cabría esperar. Claramente, el autor se ha quemado con los dedos en estos temas unas pocas veces ... Su respaldo más simple es probablemente lo suficientemente bueno para la mayoría de los casos, y permite que los casos exóticos se usen para engañar al software que necesita engañar. – RBerteig

+0

Mis usuarios probablemente nunca hayan escuchado del comando 'subst', y mi código C simple ha funcionado perfectamente hasta el momento. – steveha

+0

la gran sorpresa para nosotros los veteranos es que 'subst' todavía existe ... incluso está presente en Win7 64bit, pero se remonta a DOS 5.0 si no antes. Win7 viene con un montón de JUNCTIONS para compatibilidad con versiones anteriores. Eso es dar algunos de mis antiguos scripts Perl que deambulan por el sistema de archivos, ya que no son exactamente directorios y ciertamente no son archivos. Un ejemplo es que 'C: \ Documents and Settings' es una JUNCTION asignada a' C: \ Users'. – RBerteig