Path.Combine absoluto con cadenas de ruta relativas

94

Estoy tratando de unirme a una ruta de Windows con una ruta relativa usando Path.Combine.

Sin embargo, Path.Combine(@"C:\blah",@"..\bling")devuelve en C:\blah\..\blinglugar de C:\bling\.

¿Alguien sabe cómo lograr esto sin escribir mi propio solucionador de rutas relativas (que no debería ser demasiado difícil)?

CVertex
fuente
5
Estamos recibiendo diferentes respuestas aquí ... No creo que sea un duplicado
CVertex
1
es duplicado, aunque creo que Path.GetFullName es una mejor solución.
Greg Dean
Simplemente te contradeciste. Pero gracias por la respuesta alternativa.
CVertex
posible duplicado de Path.Combine y la notación de puntos
Julien Bérubé

Respuestas:

63

Que funciona:

string relativePath = "..\\bling.txt";
string baseDirectory = "C:\\blah\\";
string absolutePath = Path.GetFullPath(baseDirectory + relativePath);

(resultado: absolutePath = "C: \ bling.txt")

Lo que no funciona

string relativePath = "..\\bling.txt";
Uri baseAbsoluteUri = new Uri("C:\\blah\\");
string absolutePath = new Uri(baseAbsoluteUri, relativePath).AbsolutePath;

(resultado: absolutePath = "C: /blah/bling.txt")

Llyle
fuente
8
Sí, eso es lo que estoy insinuando con el post
Llyle
7
Solo asegúrese de que baseDirectory tenga el \\ final, de lo contrario terminará con C:\\blah..\\bling.txty eso no funcionará. En ese caso, puede agregarlos manualmente a la cadena o hacerloPath.GetFullPath(Path.Combine(baseDirectory, relativePath))
Nelson Rothermel
5
¿No debería ser el resultado de tu sección What WorksC:\bling.txt ?
cod3monk3y
¿Por qué no funciona el método basado en URI? De acuerdo con esta respuesta , el resultado es válido (y parece que también se reconoce en Windows ).
FH
37

Llame a Path.GetFullPath en la ruta combinada http://msdn.microsoft.com/en-us/library/system.io.path.getfullpath.aspx

> Path.GetFullPath(Path.Combine(@"C:\blah\",@"..\bling"))
C:\bling

(Estoy de acuerdo que Path.Combine debería hacer esto por sí mismo)

Coronel Panic
fuente
Tenga en cuenta que esto solo funciona si la primera ruta es una ruta absoluta. No funciona paraPath.GetFullPath(Path.Combine(@"..\..\blah",@"\bling"))
derekantrican
16

Path.GetFullPath(@"c:\windows\temp\..\system32")?

Shahkalpesh
fuente
2
Nota: debería resultar enc:\windows\system32
cod3monk3y
4

Para las aplicaciones universales de Windows Path.GetFullPath()no está disponible, puede usar la System.Uriclase en su lugar:

 Uri uri = new Uri(Path.Combine(@"C:\blah\",@"..\bling"));
 Console.WriteLine(uri.LocalPath);
thumbmunkeys
fuente
3

Esto le dará exactamente lo que necesita (la ruta NO tiene que existir para que esto funcione)

DirectoryInfo di = new DirectoryInfo(@"C:\blah\..\bling");
string cleanPath = di.FullName;
Jonathan Mc Namee
fuente
1
Tanto Path.GetFullPath () como DirectoryInfo.FullName funcionarán en una ruta ficticia. El problema es que cuando el archivo existe realmente, el proceso de ejecución necesita FileIOPermission, cierto para ambas API. (ver MSDN)
Paul Williams
1

Tenga cuidado con las barras invertidas, no las olvide (ni las use dos veces :)

string relativePath = "..\\bling.txt";
string baseDirectory = "C:\\blah\\";
//OR:
//string relativePath = "\\..\\bling.txt";
//string baseDirectory = "C:\\blah";
//THEN
string absolutePath = Path.GetFullPath(baseDirectory + relativePath);
zaknafein
fuente
0

Path.GetFullPath() no funciona con rutas relativas.

Aquí está la solución que funciona con rutas relativas + absolutas. Funciona tanto en Linux como en Windows y mantiene ..como se esperaba al principio del texto (en reposo se normalizarán). La solución aún depende Path.GetFullPathde hacer la corrección con una pequeña solución.

Es un método de extensión, utilícelo como text.Canonicalize()

/// <summary>
///     Fixes "../.." etc
/// </summary>
public static string Canonicalize(this string path)
{
    if (path.IsAbsolutePath())
        return Path.GetFullPath(path);
    var fakeRoot = Environment.CurrentDirectory; // Gives us a cross platform full path
    var combined = Path.Combine(fakeRoot, path);
    combined = Path.GetFullPath(combined);
    return combined.RelativeTo(fakeRoot);
}
private static bool IsAbsolutePath(this string path)
{
    if (path == null) throw new ArgumentNullException(nameof(path));
    return
        Path.IsPathRooted(path)
        && !Path.GetPathRoot(path).Equals(Path.DirectorySeparatorChar.ToString(), StringComparison.Ordinal)
        && !Path.GetPathRoot(path).Equals(Path.AltDirectorySeparatorChar.ToString(), StringComparison.Ordinal);
}
private static string RelativeTo(this string filespec, string folder)
{
    var pathUri = new Uri(filespec);
    // Folders must end in a slash
    if (!folder.EndsWith(Path.DirectorySeparatorChar.ToString())) folder += Path.DirectorySeparatorChar;
    var folderUri = new Uri(folder);
    return Uri.UnescapeDataString(folderUri.MakeRelativeUri(pathUri).ToString()
        .Replace('/', Path.DirectorySeparatorChar));
}
U. Bulle
fuente