J'ai un sous-système de fichiers complet à l' intérieur d' un chemin /home/user/system
contenant la structure standard Linux avec des répertoires /bin
, /home
, /root
, /usr
, /var
, /etc
, ...
Ce sous-système de fichiers contient des liens symboliques, relatifs ou absolus. Les liens symboliques relatifs sont très bien, ils restent dans le sous-système de fichiers sous /home/user/system
. Mais les liens symboliques absolus sont problématiques, car ils pointent vers une cible en dehors du sous-système de fichiers.
À titre d'exemple, nous supposons un lien symbolique absolu comme suit (vu à l'intérieur du sous-système de fichiers):
/usr/file1 -> /usr/lib/file1
Dans le système de fichiers global, nous avons un lien /home/user/system/usr/file1
qui pointe maintenant vers un fichier /usr/lib/file1
à l'extérieur du sous-système de fichiers, au lieu d'un fichier /home/user/system/usr/lib/file1
à l' intérieur du sous-système de fichiers.
Je voudrais avoir un script simple, de préférence une seule ligne de commande (rsync, chroot, find, ...) qui convertit chaque lien symbolique absolu en un lien relatif.
Dans l'exemple donné, ce lien relatif deviendrait
/usr/file1 -> ../usr/lib/file1
la source
Réponses:
Avec l'
symlinks
utilitaire de Mark Lord (offert par de nombreuses distributions; si le vôtre ne l'a pas, construisez-le à partir de la source ):Alternativement, sur les systèmes qui ont une
readlink
commande et un-lname
prédicat pourfind
(avertissement: code non testé):la source
_ {} +
à la fin de la découverte? De plus, j'obtiens une erreurfind: paths must precede expression: ksh
qui ne semble pas avoir de sens (car le chemin précède l'expression ksh)._
est$0
pour l'extrait de coquille, et{} +
est remplacée par la liste des arguments qui deviennent$1
,$2
etc. , quifor link; do …
passe en boucle sur (il est synonymefor link in "$@"; do …
). L'erreurfind
est due à une faute de frappe (j'ai réussi à taper des guillemets au lieu de guillemets simples autour de l'argument-lname
).symlinks
? Cela résoudrait votre problème - c'est essentiellement pour cela qu'il a été conçu (avec l'ennui que vous devez l'exécuter en chrooté ( fakechroot devrait faire l'affaire)).Pure bash & coreutils, change les liens symboliques en relatifs sans
../
s inutiles dans le chemin:Vous pouvez changer:
find .
pourfind /path/to/directory
convertir les liens symboliques dans ce répertoireln -fs
àecho ln -fs
une course sècheExplication:
target="$(realpath "$l")"
- trouve le chemin absolu vers la cible du lien symboliqueln -fs
- crée symlink (-s
), forçant (-f
) la réécriture de l'existantrealpath -s "$l"
- trouve un chemin absolu pour se lier symboliquementdirname "$(realpath -s "$l")"
- trouve le chemin absolu vers le répertoire contenant le lien symboliquerealpath --relative-to="$(dirname "$(realpath -s "$l")")" "$target"
- trouve le chemin de la cible par rapport au lien symbolique, en d'autres termes: convertit l'absolu en chemin relatifla source
if
clause pour ignorer les liens brisés.Cet extrait de bash devrait le faire. Le premier formulaire imprimera ce qu'il fera; le second le fera. Je voudrais examiner attentivement la sortie car elle est destructrice - la
ln -f
remplace le lien existant.la source
Voici une solution pure sh.
la source
La transformation absolue en liens relatifs est prise en charge par sshfs qui monte les répertoires distants via ssh.
La commande est: Là
La commande, en particulier la
<placeholders>
, doit être adaptée à l'environnement spécifique.la source