Wie „findet“ man, während man bestimmten symbolischen Links unter Linux folgt?

Wie „findet“ man, während man bestimmten symbolischen Links unter Linux folgt?

Ich möchte findDateien (mit ähnlichen Merkmalen) finden, aber bestimmten symbolischen Links folgen und nur diesen folgen (durch Mustervergleich).

Offenbar findkommt es selbst nicht damit klar: Es gibt keine Option zum Einrichten des Symlink-Follow-Verhaltens, und eine naive Lösung find -Lfunktioniert problemlos (oder ist extrem langsam).

Antwort1

Der letzte Satz der Frage lässt vermuten, dass das Problem nicht beim Verfolgen von Symlinks im Allgemeinen liegt (und z. B. beim Anwenden -newerauf den Symlink in einem Fall und auf das Ziel in einem anderen Fall), sondern beim Verfolgen von Symlinkszu Verzeichnissenund somit dorthin zu gelangen, wo Sie nicht hinwollen.

ProSpezifikation, findsoll Endlosschleifen erkennen, sodass es nicht zu einem Livelock kommen sollte. Verschwendete Ressourcen (einschließlich Zeit) können ein Problem sein und ich verstehe Ihre Besorgnis.

Verwenden Sie zunächst, -Lum das Folgen von Symlinks zuzulassen find, denen Sie folgen möchten. Dann benötigen Sie eine Möglichkeit, andere Symlinks zu erkennen.

In find -L -type list nie wahr, aber Sie können Symlinks mit erkennen -exec test -L {} \;(denken Sie daran -exec … \;, dass es sich auch um einen Test handelt. Er ist erfolgreich, wenn der innere Befehl mit dem Status 0 beendet wird). Auf diese Weise können Sie immer noch einige Tests speziell auf Symlinks anwenden und -prune(oder nicht) entsprechend.

Beispielsweise führt der folgende Befehl nur symbolische Links aus, deren Namen mit beginnen foooder enden bar:

find -L . -exec test -L {} \; ! \( -name 'foo*' -o -name '*bar' \) -prune -o -print

Platzieren Sie den Ausdruck, den Sie ursprünglich wollten, nach -prune -o. Im obigen Befehl ist der „ursprüngliche“ Ausdruck -print. Denken Sie daran , -execdass das implizite unterdrückt wird . -printWenn Sie es -printalso brauchen, fügen Sie es explizit hinzu (wie wir es getan haben).

Beachten Sie, dass -nameder Name des Symlinks selbst getestet wird. Wenn Sie den Namen des Ziels testen möchten, benötigen Sie realpathmöglicherweise basenameShell-Code. Beispiel:

find -L . -exec test -L {} \; -exec sh -c '
   case "$(basename "$(realpath "$1")")" in
      baz* ) exit 0 ;;
      *qux ) exit 1 ;;
   esac
   exit 0
' find-sh {} \; -prune -o -print

Der obige Befehl erstellt -pruneeinen symbolischen Link zu allen Dateien, deren Name mit beginnt baz, führt aber auch symbolische Links zu Verzeichnissen aus, deren Namen mit enden qux(sofern sie nicht mit beginnen baz), und schließlich -prunezu allen anderen symbolischen Links.

Anmerkungen:

  • realpathund basenamesind nicht portierbar.
  • realpathlöst alle symbolischen Links auf.
  • Das Verhalten im Falle eines defekten symbolischen Links entspricht möglicherweise Ihren Erwartungen, muss es aber nicht.
  • Das separate Aufrufen testfür jede Datei beeinträchtigt die Leistung, aber ich habe keine bessere Möglichkeit gefunden. Das Aufrufen von shund realpathist basenamein dieser Hinsicht ebenfalls schlecht, aber hier geschieht dies nur für symbolische Links, sodass die Auswirkungen in den meisten Fällen begrenzt sein werden.
  • find-shwird hier erklärt:Was ist das zweite sh in sh -c 'some shell code' sh?
  • -pruneIn den Beispielen werden Pfadnamen, die d erhalten, nicht -printbearbeitet. Ändern Sie das letzte Fragment in -prune -false -o -printund sie werden gedruckt. SieheErläuterung-false; für den Fall, dass Sie sie brauchen, gibt es eine tragbare Alternative .

verwandte Informationen