Wie kann ich Dateien auflisten, für die keine Symlinks vorhanden sind?

10

Ich habe ein großes "myfiles" -Verzeichnis voller verschiedener Dokumente und möchte seine Struktur nicht ändern.

Ich habe daher (mehrere) andere Verzeichnisse für jede Dokumentklasse erstellt. Zum Beispiel habe ich ein "images" -Verzeichnis, das Symlinks zu jedem .jpgoder einer .cr2Datei im "myfiles" -Verzeichnis sowie weitere beschreibende Dateien für jeden Symlink (mit demselben Dateinamen) mit Beschreibung und anderen Metadaten enthält. Die Symlinks im Verzeichnis / images haben möglicherweise einen anderen Namen als die ursprünglich verknüpfte Datei.

Ich versuche den einfachsten Weg zu finden, um sicherzustellen, dass jede Bilddatei im Verzeichnis "myfiles" einen Symlink zum Verzeichnis "images" hat.

Sehen Sie sich ein Beispiel für die Ordnerstruktur an

/myfiles/a.doc
/myfiles/b.jpg
/myfiles/c.cr2
/myfiles/d.mov

sollte resultieren

/images/b_800x600.jpg
/images/b_800x600.desc
/images/c_3820x5640.cr2
/images/c_3820x5640.cr2
Robert Alexander
quelle
Keine vollständige Antwort, aber Sie können die Ergebnisse von a find /myfiles -type fin einer Datei speichern und dann verwenden find /images -type l -exec readlink {} \; | egrep myfiles, um eine Liste der Dateien zu erhalten, die mit Symlinks verknüpft sind. /imagesAnschließend können Sie die Ergebnisse durchlaufen und sedjeweils eine ausführen , um die Pfade in der ersten Datei zu löschen, die Sie speichern, da sie bereits vorhanden sind Haben Sie den Symlink und die verbleibenden Dateien sind die Dateien, die den Symlink nicht haben.
Bratchley
2
Können Sie stattdessen Hardlinks verwenden, um mithilfe des Hardlink-Zählers festzustellen, ob Sie Links haben? Mit ls -lkönnen Sie die Anzahl der Hardlinks in der zweiten Spalte sehen.
Lambert
Mach was @Lambert sagt. rmDiese Symlink-Verzeichnisse werden pax -rwl -s "\|.*regex|modifes_filename|" /path/to/myfiles/*.jpg /path/to/jpg_dirbeispielsweise verwendet, um Hardlinks mit programmgesteuert geänderten Dateinamen nur für diejenigen Dateien abzurufen, die Ihren JPGs entsprechen. Sie können viel mehr als das
herausholen

Antworten:

6

Wenn ich die Frage richtig verstanden habe, benötigen Sie Dateien in myfiles, die keine Symlinks in Bildern enthalten:

#!/bin/bash

OIFS="$IFS"
IFS=$'\n'

files="$(find myfiles/ -type f -name '*.jpg' -or -name '*.cr2')"
for f in $files; do
    list="$(find -L images/ -xtype l -samefile "$f")"
    if [[ "$list" == "" ]]; then
        echo "$f does not have symlink."
    fi
done

IFS="$OIFS"

Bei diesem Ansatz gibt es eine Einschränkung, wenn Sie die Datei a.jpg im Verzeichnis myfiles / 1 haben und einen Symlink zu dieser Datei im Verzeichnis images / 3 oder einfach in images / haben. Die Datei wird nicht mit fehlendem Symlink gemeldet.

Taliezin
quelle
Vielen Dank ! Ja, du hast es richtig verstanden. Nah aber nicht ganz. Meine Schuld ist nicht deine :-) Das Beispiel, das ich gegeben habe, zeigt ein vereinfachtes myfiles-Verzeichnis. In Wirklichkeit können sich die Bilddateien unter myfiles in einer beliebigen Ebene verschachtelter Verzeichnisse befinden.
Robert Alexander
Ich habe die Antwort bearbeitet, um in ganzen Myfiles zu suchen, aber überprüfe, ob dies das ist, was du wünschst.
Taliezin
FAST da :-) Ihr Skript hat Probleme, wenn Dateien Leerzeichen enthalten (und vielleicht auch anderen Mist wie einzelne Apostrophe "...
Robert Alexander
Ich denke jetzt sollte es ok sein
taliezin
Ihre letzte Änderung teilt jedes f beim Auftreten jedes Buchstabens n! :-) Ich habe die IFS-Zeile auf IFS = dann eine neue Zeile von der Tastatur und dann eine andere geändert. Jetzt scheint die Aufteilung zu funktionieren, aber ich erhalte eine lange Folge von "Missinglinks.sh: 11: Missinglinks.sh: [[: nicht gefunden" "
Robert Alexander
3

Ich myfilesgehe davon aus, dass die Dateien unter keine symbolischen Links sind und dass keiner der Dateinamen Zeilenumbrüche enthält. (Mein Ansatz kann immer noch funktionieren, wenn diese Annahmen verletzt werden, aber er wird komplizierter.) Ich gehe auch davon aus, dass Sie das gemeinsame readlinkDienstprogramm haben und dass es die -fKanonisierung von Pfaden unterstützt, was unter Linux (sowohl GNU als auch BusyBox) der Fall ist, aber nicht auf zB OSX.

Erstellen Sie eine Liste mit Dateien und sortieren Sie sie nach Maß:

find /myfiles -type f -print | sort >all.list

Erstellen Sie eine Liste symbolischer Verknüpfungsziele mit absoluten Pfaden.

find /images -type f -exec readlink -f {} \; | sort >linked.list

Listen Sie die nicht verknüpften Dateien auf:

comm -32 all.list linked.list

Wenn Sie eine Shell verwenden, die die Prozessersetzung unterstützt, können Sie alles in einem Befehl zusammenfassen:

comm -23 <(find /myfiles -type f -print | sort) \
         <(find /images -type f -exec readlink -f {} \; | sort)

Wenn die Links unter /imagesabsolut sind, können Sie readlinkohne die -fOption verwenden, die unter * BSD und OSX verfügbar ist.

Gilles 'SO - hör auf böse zu sein'
quelle
Ich wollte so etwas wie Ihren commBefehl posten, aber ich werde es jetzt nicht tun, da ich sehe, dass Sie es bereits getan haben. Die Weiterleitung von sortmacht jedoch keinen Sinn; dann geben die Prozessersetzungen nichts aus. Sie können auch viele Verzeichnisse neben hinzufügen, /imageswenn Sie Dateien suchen möchten, in /myfilesdenen keine Verknüpfung mit einem der verschiedenen Verzeichnisse besteht /images.
Tripleee
1
Siehe stackoverflow.com/questions/7665/… für Alternativen zureadlink -f
Tripleee
@tripleee Ich habe vergessen, die Umleitung zu entfernen, als ich die Prozessumleitungsversion erstellt habe, danke. Ja, Sie können problemlos andere Verzeichnisse hinzufügen oder andere Variationen vornehmen.
Gilles 'SO - hör auf böse zu sein'