Comment calculer un chemin relatif à partir de deux chemins absolus dans le shell Linux?

17

Nous avons deux voies. Le premier est le répertoire, le second soit un répertoire ou un fichier.

/a/b/c et /a/d/e.txt

Le chemin relatif du premier au deuxième sera:

../../d/e.txt

Comment calculer cela dans un terminal Linux? Pour ceux qui demandent «Quel est le cas d'utilisation?», On pourrait utiliser cela, par exemple, pour créer de nombreux liens symboliques relatifs.

techraf
la source
1
Cela n'aurait pas dû être migré.
1
Il aurait dû être fermé en double.
pause jusqu'à nouvel ordre.

Réponses:

10

En supposant que GNU coreutils:

  • Pour les liens symboliques, ln a récemment appris l' --relativeoption.

  • Pour tout le reste, realpathprend en charge les options --relative-to=et --relative-base=.

user1686
la source
1
Comment faites-vous avec BusyBox?
DUzun
4

Pour moi, cette réponse (qui utilise un oneliner en python) fonctionne parfaitement.

$ python -c "import os.path; print os.path.relpath('/a/d/e.txt', '/a/b/c')"
../../d/e.txt

Testé avec succès sur Linux (Kubuntu 14.04) et sur Mac OSX, nécessite Python 2.6.

Joe
la source
2

Pour ne pas dépendre de ce realpathqui n'est pas toujours disponible et minimiser les dépendances, j'ai trouvé cela (en utilisant un peu d'aide de cette réponse ):

function relative_path_from_to() {
  # strip trailing slashes
  path1=${1%\/}
  path2=${2%\/}
  # common part of both paths
  common=$(printf '%s\x0%s' "${path1}" "${path2}" | sed 's/\(.*\).*\x0\1.*/\1/')
  # how many directories we have to go up to the common part
  up=$(grep -o "/" <<< ${path1#$common} | wc -l)
  # create a prefix in the form of ../../ ...
  prefix=""; for ((i=0; i<=$up; i++)); do prefix="$prefix../"; done
  # return prefix plus second path without common
  printf "$prefix${2#$common}"
}

Génère un sous-shell pour trouver la partie commune des deux chemins. Peut-être que vous l'aimez - fonctionne pour moi.

Pascal
la source