Suchen Sie alle symbolischen Links in einem Verzeichnisbaum, der außerhalb dieses Baums zeigt

8

Ich verschiebe häufig Verzeichnisbäume an andere Speicherorte oder kopiere ihre Tarballs auf andere Computer, und ich möchte eine Methode haben, um zu überprüfen, ob Symlinks in einem Verzeichnisbaum A auf Speicherorte außerhalb von A verweisen, da diese beim Verschieben / Kopieren unterbrochen werden Verzeichnis.

Marcus Junius Brutus
quelle

Antworten:

7

Sie möchten ein Programm namens realpath, das in Verbindung mit verwendet wird find.

Z.B:

find . -type l -exec realpath {} \; | grep -v "^$(pwd)"
Bahamat
quelle
1
Die von Ihnen bereitgestellte Beschwörung meldet nur den fehlerhaften Zielort, nicht den Symlink, der darauf verweist. Als solches habe ich meine Akzeptanz entfernt. Bitte sehen Sie meine "Antwort" unten: unix.stackexchange.com/a/308899/24044 und wenn Sie damit zufrieden sind (oder es verbessern), werde ich meine "Antwort" löschen und Ihre Frage erneut akzeptieren.
Marcus Junius Brutus
2

Verwenden Sie bindfs , um eine weitere Ansicht dieses Verzeichnisbaums zu erstellen.

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

Verwenden Sie dann das Dienstprogramm symlinks (das von vielen Distributionen geliefert oder aus dem Quellcode kompiliert wird ), um dateisystemübergreifende Links zu erkennen.

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

(Beachten Sie, dass beim Parsen der Ausgabe davon ausgegangen wird, dass Ihre symbolischen Links und ihre Ziele weder Zeilenumbrüche noch Pfade zu symbolischen Links den Teilstring enthalten  -> .) Mit demselben Dienstprogramm können auch absolute Symlinks in relative konvertiert werden (dies möchten Sie jedoch von) der ursprüngliche Ort).

Gilles 'SO - hör auf böse zu sein'
quelle
2

Mit zsh:

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

Wenn das Verzeichnis ist /foound Sie haben, /foo/bardass es sich um einen Symlink /foo/bazhandelt, ist dies ein Link, dessen Ziel sich in / foo befindet, aber nach dem Verschieben wird der Link immer noch unterbrochen, sodass Sie möglicherweise auch Symlinks mit absoluten Pfaden abgleichen möchten.

Aber selbst dann ein bar => ../foo/bazin /foowürde ein Problem (falsch negativ) sein, würde so ein , a => bwo bein symbolischen Link außerhalb des Baumes (falsch positiv, je nachdem wie man es sehen will)

Stéphane Chazelas
quelle
2

Ich musste die Antwort von @bahamat ein wenig optimieren, damit es funktioniert.

Die bereitgestellte Version meldete lediglich den beleidigenden absoluten Ort, nicht jedoch den Symlink, der darauf verweist.

Folgendes habe ich verwendet (ich bin sicher, dass es verbessert werden kann):

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
quelle
Ich fand, dass dies das nützlichste Skript ist: for f in $(find . -type l); do echo $(realpath -m -q $f) '<-' $f; done | grep-v "^$(pwd)"(vor allem -mund -qdas defekte und nicht externe Links herausfiltert)
Adam Lindberg
1

GNU Coreutils hat bewiesen realpath, dass Symlinks aufgelöst werden. Auf diese Weise können Sie das Ziel jedes Symlinks mit dem aktuellen Arbeitsverzeichnis vergleichen.

#!/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
Doppelpunkte
quelle
Mehrere Probleme: Nein -type l, keine -rOption read, IFS nicht bereinigt read, $filenamenicht zitiert, $PWDals regulärer Ausdruck behandelt, Pfade mit Zeilenumbruchzeichen, die nicht berücksichtigt wurden, /foobarwürden für $PWD== "/ foo"
Stéphane Chazelas