2009-03-19 7 views
3

Je suis en train de refactoriser du code C# et une partie de ceci est de refaire quelques références, parce que nous refaisons entièrement la structure des dossiers. Ce que je voudrais faire est de simplement aller dans le fichier .csproj ou .sln et modifier les chemins.Meilleur/le plus simple/le moyen le plus rapide d'obtenir un chemin relatif entre deux fichiers?

Toutefois, certaines des références ont des chemins comme

"../../../../../../ThirdParty/SomeMicrosoftLibrary/bin/Debug/SomeMicrosoftLibrary.dll 

Et puisque nous avons tout déplacions je dois trouver le nouveau chemin relatif. Mais je déteste absolument essayer de faire cela (déterminer combien de barres obliques et de périodes je dois mettre dans) car il se sent toujours comme un peu hasardeux de la science.

Existe-t-il un moyen simple (utilitaire, script, extrait de code) de dire "voici le fichier A, voici le fichier B, quel est le chemin relatif du fichier B par rapport au fichier A?"

Répondre

7

Avec Ruby:

$ ruby -e "require 'pathname'; puts Pathname.new('foo/bar').relative_path_from(Pathname.new('baz/x/y/z')).to_s" 
../../../../foo/bar 

Je suis assez sûr que Python a une méthode similaire, bien que je ne l'ai pas à portée de main.

+0

Je ne pense pas qu'il y ait une telle méthode dans la bibliothèque standard de Python, mais une recherche Google donne beaucoup d'exemples. –

+0

* vérifie * N'est-ce pas os.path.relpath (a, b)? –

+0

J'épouserais Ruby si c'était possible =) – ioquatix

2

Je sais que c'est vieux, mais je cherchais la réponse à cette alors voici une méthode qui le fait, juste au cas où cela pourrait aider quelqu'un d'autre dans l'avenir

/// <summary> 
/// Finds the relative path of B with respect to A 
/// </summary> 
/// <param name="A">The path you're navigating from</param> 
/// <param name="B">The path you're navigating to</param> 
/// <returns></returns> 
static string Get_PathB_wrt_PathA(string A, string B) 
{ 
    string result = ""; 

    if (A == B) 
     return result; 

    var s = new char[] { '\\' }; 
    var subA = A.Split(s, StringSplitOptions.RemoveEmptyEntries).ToList(); 
    var subB = B.Split(s, StringSplitOptions.RemoveEmptyEntries).ToList(); 

    int L = subA.Count >= subB.Count ? subB.Count : subA.Count; 
    int i = 0; 

    for (i = 0; i < L; i++) 
    { 
     if (subA[0] == subB[0]) 
     { 
      subA.RemoveAt(0); 
      subB.RemoveAt(0); 
     } 
     else 
      break; 
    } 

    for (i = 0; i <= subA.Count - 1; i++) 
    { 
     result += @"..\"; //this navigates to the preceding directory 
    } 

    for (i = 0; i < subB.Count; i++) 
    { 
     result += subB[i] + "\\"; 
    } 

    result = result.Substring(0, result.Length - 1); //remove the extra backslash 
    return result; 
} 
+0

Ne devrait-il pas y avoir une vérification pour s'assurer que 'résultat' a une antislash arrière avant d'essayer de prendre la sous-chaîne? Si A et B sont exactement les mêmes chemins, cela échouera. Je n'écris pas C#, mais dans d'autres langages il va produire une exception car vous essayez de prendre une sous-chaîne de longueur -1. – Bryan

+0

De plus, si A et B sont égaux, vos boucles for deviennent infinies. (subA.Count - 1) = (0 - 1) = -1, qui ne satisfera jamais la condition de fin de boucle: i <-1. La boucle s'incrémente simplement pour toujours. Encore une fois, pas familier avec C# alors peut-être qu'il y a des fonctionnalités de langue qui empêchent cela. Mais dans d'autres langues, le modèle ci-dessus nécessite quelques vérifications de sécurité. – Bryan

+0

J'ai ajouté une vérification pour A == B, car c'est un gaspillage de faire tourner le reste de la logique si nous savons déjà qu'ils sont égaux. La boucle ne serait pas infinie s'ils étaient égaux. Toutes les boucles sont incrémentées de façon positive Pour les boucles, il n'y a pas de risque que l'une ne se termine pas. De plus, en ce qui concerne la barre oblique inverse, j'ai changé la condition dans la deuxième boucle pour être un <= au lieu d'un <(c'était un bogue) et avec la vérification en haut pour A et B étant égaux, il ne devrait plus y avoir de être tous les cas où la chaîne ne se terminerait pas avec un antislash supplémentaire – Anthony

Questions connexes