trouver tous les liens symboliques dans une arborescence de répertoires pointant à l'extérieur de cette arborescence

8

Je déplace fréquemment des arborescences de répertoires vers d'autres emplacements ou copie leurs archives tar sur d'autres machines, et j'aimerais avoir une méthode pour vérifier si des liens symboliques dans une arborescence de répertoires A pointent vers des emplacements en dehors de A car ils seront rompus dans le déplacé / copié annuaire.

Marcus Junius Brutus
la source

Réponses:

7

Vous voulez un programme appelé realpath, utilisé en conjonction avec find.

Par exemple:

find . -type l -exec realpath {} \; | grep -v "^$(pwd)"
bahamat
la source
1
L'incantation que vous fournissez ne signale que l'emplacement cible incriminé, pas le lien symbolique qui pointe vers celui-ci. En tant que tel, j'ai retiré mon acceptation. Veuillez voir ma "réponse" ci-dessous: unix.stackexchange.com/a/308899/24044 et si vous en êtes satisfait (ou l'améliorez), je supprimerai ma "réponse" et accepterai à nouveau votre question.
Marcus Junius Brutus
2

Utilisez bindfs pour créer une autre vue de cette arborescence de répertoires.

mkdir /tmp/view
bindfs /some/directory /tmp/view

Utilisez ensuite l' utilitaire symlinks (fourni par de nombreuses distributions ou compilez-le à partir de la source ) pour détecter les liens entre les systèmes de fichiers.

symlinks -r /tmp/view | sed -n 's/^\(absolute\|other_fs\): //p'

(Notez que l'analyse de la sortie suppose que vos liens symboliques et leurs cibles ne contiennent pas de sauts de ligne, pas plus que les chemins vers les liens symboliques ne contiennent la sous-chaîne  -> .) Ce même utilitaire peut également convertir des liens symboliques absolus en relatifs (mais vous voudriez le faire à partir de l'emplacement d'origine).

Gilles 'SO- arrête d'être méchant'
la source
2

Avec zsh:

cd -P -- "$dir"
for i (**/*(ND@)) [[ $i:A = $PWD/* ]] || [[ $i:A = $PWD ]] || print -r -- "$i => $i:A"

Maintenant, si le répertoire est /fooet que vous avez /foo/barun lien symbolique vers /foo/baz, c'est un lien dont la cible est dans / foo, mais une fois déplacé, le lien sera toujours rompu, vous voudrez peut-être également faire correspondre les liens symboliques aux chemins absolus.

Mais même dans ce cas, un bar => ../foo/bazin /fooserait un problème (faux négatif), tout comme un a => bbest un lien symbolique en dehors de l'arbre (faux positif, selon la façon dont vous voulez le voir)

Stéphane Chazelas
la source
2

J'ai dû modifier un peu la réponse donnée par @bahamat pour que cela fonctionne.

La version fournie a simplement signalé l'emplacement absolu incriminé, mais pas le lien symbolique qui y pointe.

Voici ce que j'ai utilisé (je suis sûr qu'il peut être amélioré):

for f in $(find . -type l ); do echo -n $(realpath $f) && echo -n "|" && echo $f ; done | grep -v "^$(pwd)" | cut -d \| -f 2 
Marcus Junius Brutus
la source
J'ai trouvé que c'était le script le plus utile: for f in $(find . -type l); do echo $(realpath -m -q $f) '<-' $f; done | grep-v "^$(pwd)"(notamment -met -qqui filtre les liens rompus et non externes)
Adam Lindberg
1

GNU coreutils prouve realpath, qui résout les liens symboliques. Avec cela, vous pouvez comparer la cible de chaque lien symbolique au répertoire de travail actuel avec quelque chose comme:

#!/bin/bash

find . | while read filename
do
  if realpath $filename | grep -E "^$PWD" > /dev/null
  then
    echo 'this file is safe'
  else
    echo 'this file links externally'
  fi
done
deux points
la source
Plusieurs problèmes: non -type l, aucune -roption pour read, IFS non filtré read, $filenamenon cité, $PWDtraité comme une expression régulière, les chemins avec des caractères de nouvelle ligne non pris en compte, /foobarcorrespondraient à $PWD== "/ foo"
Stéphane Chazelas