2009-07-25 09:41:26 +0000 2009-07-25 09:41:26 +0000
104
104

Wie können Sie den tatsächlichen harten Link mit ls sehen?

Ich führe

ln /a/A /b/B

aus und möchte im Ordner a sehen, worauf die Datei A mit ls zeigt.

Antworten (9)

182
182
182
2009-07-25 10:01:32 +0000

Sie können die Inode-Nummer für Ihre Datei mit

ls -i

finden und

ls -l

zeigt die Anzahl der Referenzen (Anzahl der Hardlinks zu einem bestimmten Inode)

nachdem Sie die Inode-Nummer gefunden haben, können Sie nach allen Dateien mit demselben Inode suchen:

find . -inum NUM

zeigt die Dateinamen für Inode NUM im aktuellen Verzeichnis (.)

66
66
66
2009-07-25 09:51:57 +0000

Es gibt nicht wirklich eine eindeutige Antwort auf Ihre Frage. Im Gegensatz zu Symlinks sind Hardlinks nicht von der “Originaldatei” zu unterscheiden.

Verzeichniseinträge bestehen aus einem Dateinamen und einem Zeiger auf einen Inode. Der Inode wiederum enthält die Datei-Metadaten und (Zeiger auf) den eigentlichen Dateiinhalt). Das Erstellen eines Hardlinks erzeugt einen weiteren Dateinamen + Verweis auf denselben Inode. Diese Referenzen sind unidirektional (zumindest in typischen Dateisystemen) - die Inode führt nur einen Referenzzähler. Es gibt keine Möglichkeit, herauszufinden, welches der “ursprüngliche” Dateiname ist.

Das ist übrigens der Grund, warum der Systemaufruf zum “Löschen” einer Datei unlink heißt. Er entfernt nur einen Hardlink. Die Inode und die angehängten Daten werden nur gelöscht, wenn die Anzahl der Verweise auf die Inode auf 0 sinkt.

Die einzige Möglichkeit, die anderen Verweise auf eine bestimmte Inode zu finden, besteht darin, das Dateisystem erschöpfend zu durchsuchen und zu prüfen, welche Dateien auf die betreffende Inode verweisen. Sie können ‘test A -ef B’ von der Shell aus verwenden, um diese Prüfung durchzuführen.

24
24
24
2009-07-25 10:01:38 +0000
ls -l

Die erste Spalte stellt die Berechtigungen dar. Die zweite Spalte wird die Anzahl der Unterpunkte (bei Verzeichnissen) oder die Anzahl der Pfade zu den gleichen Daten (Hardlinks, einschließlich der Originaldatei) zur Datei sein. Beispiel:

-rw-r--r--@ 2 [username] [group] [timestamp] HardLink
-rw-r--r--@ 2 [username] [group] [timestamp] Original
               ^ Number of hard links to the data
14
14
14
2013-08-15 08:52:16 +0000

Wie wäre es mit der folgenden, einfacheren Variante? (Letzteres könnte die langen Skripte oben ersetzen!)

Wenn Sie eine bestimmte Datei <THEFILENAME> haben und alle ihre Hardlinks über das Verzeichnis <TARGETDIR> verteilt wissen wollen (was sogar das gesamte Dateisystem sein kann, das durch / bezeichnet wird),

find <TARGETDIR> -type f -samefile <THEFILENAME>

Erweitern Sie die Logik, wenn Sie alle Dateien im Verzeichnis <SOURCEDIR> mit mehreren Hardlinks über <TARGETDIR> verteilt wissen wollen:

find <SOURCEDIR> -type f -links +1 \
  -printf "\n\n %n HardLinks of file : %H/%f \n" \
  -exec find <TARGETDIR> -type f -samefile {} \;
6
6
6
2015-04-21 19:32:47 +0000

Es gibt eine Menge Antworten mit Skripten, um alle Hardlinks in einem Dateisystem zu finden. Die meisten von ihnen machen dumme Sachen, wie z. B. find laufen zu lassen, um das gesamte Dateisystem nach -samefile für JEDE mehrfach verknüpfte Datei zu scannen. Das ist verrückt; alles, was Sie brauchen, ist eine Sortierung nach Inode-Nummer und die Ausgabe von Duplikaten.

Mit nur einem Durchlauf durch das Dateisystem, um alle Sätze von hartverknüpften Dateien zu finden und zu gruppieren

find dirs -xdev \! -type d -links +1 -printf '%20D %20i %p\n' |
    sort -n | uniq -w 42 --all-repeated=separate

Dies ist viel schneller als die anderen Antworten, um mehrere Sätze von hartverknüpften Dateien zu finden.
find /foo -samefile /bar ist hervorragend für nur eine Datei.

  • -xdev : Begrenzung auf ein Dateisystem. Nicht unbedingt nötig, da wir die FS-id auch bei
  • ! -type d Verzeichnissen an uniq ausgeben: die . und .. Einträge bedeuten, dass sie immer verlinkt sind.
  • -links +1 : Link-Zählung streng > 1
  • -printf ... drucken FS-id, Inode-Nummer und Pfad. (Mit Auffüllen auf feste Spaltenbreiten, die wir uniq mitteilen können.)
  • sort -n | uniq ... numerisches Sortieren und Eindeutigmachen auf den ersten 42 Spalten, Trennen von Gruppen mit einer Leerzeile

Die Verwendung von ! -type d -links +1 bedeutet, dass die Eingabe von sort nur so groß ist wie die endgültige Ausgabe von uniq, so dass wir keine große Menge an Stringsortierung durchführen. Es sei denn, Sie lassen es auf einem Unterverzeichnis laufen, das nur einen aus einer Reihe von Hardlinks enthält. Wie auch immer, dies verbraucht VIEL weniger CPU-Zeit beim Durchlaufen des Dateisystems als jede andere gepostete Lösung.

Beispiel-Ausgabe:

...
            2429 76732484 /home/peter/weird-filenames/test/.hiddendir/foo bar
            2429 76732484 /home/peter/weird-filenames/test.orig/.hiddendir/foo bar

            2430 17961006 /usr/bin/pkg-config.real
            2430 17961006 /usr/bin/x86_64-pc-linux-gnu-pkg-config

            2430 36646920 /usr/lib/i386-linux-gnu/dri/i915_dri.so
            2430 36646920 /usr/lib/i386-linux-gnu/dri/i965_dri.so
            2430 36646920 /usr/lib/i386-linux-gnu/dri/nouveau_vieux_dri.so
            2430 36646920 /usr/lib/i386-linux-gnu/dri/r200_dri.so
            2430 36646920 /usr/lib/i386-linux-gnu/dri/radeon_dri.so
...

TODO?: Entpacken Sie die Ausgabe mit awk oder cut. uniq hat eine sehr eingeschränkte Feldauswahlunterstützung, daher fülle ich die Suchausgabe auf und verwende eine feste Breite. 20Zeichen ist breit genug für die maximal mögliche Inode- oder Gerätenummer (2^64-1 = 18446744073709551615). XFS wählt Inode-Nummern basierend darauf, wo auf der Platte sie zugewiesen werden, nicht zusammenhängend von 0 an, so dass große XFS-Dateisysteme >32-Bit-Inode-Nummern haben können, auch wenn sie nicht Milliarden von Dateien haben. Andere Dateisysteme können 20-stellige Inode-Nummern haben, auch wenn sie nicht gigantisch sind.

TODO: Gruppen von Duplikaten nach Pfad sortieren. Sie nach Einhängepunkt und dann nach Inode-Nummer sortiert zu haben, bringt die Dinge durcheinander, wenn Sie ein paar verschiedene Unterverzeichnisse haben, die viele Hardlinks haben. (d.h. Gruppen von Dup-Gruppen gehören zusammen, aber die Ausgabe mischt sie durcheinander).

Ein abschließendes sort -k 3 würde Zeilen separat sortieren, nicht Gruppen von Zeilen als einen einzigen Datensatz. Eine Vorverarbeitung mit etwas, um ein Paar Zeilenumbrüche in ein NUL-Byte umzuwandeln, und die Verwendung von GNU sort --zero-terminated -k 3 könnte den Zweck erfüllen. tr arbeitet allerdings nur mit einzelnen Zeichen, nicht mit 2>1 oder 1>2 Mustern. perl würde es tun (oder einfach parsen und sortieren in perl oder awk). sed könnte auch funktionieren.

3
3
3
2012-06-13 07:40:43 +0000

Dies ist eine Art Kommentar zu Torocoro-Machos eigener Antwort und Skript, aber es passt offensichtlich nicht in das Kommentarfeld._


Ich habe Ihr Skript umgeschrieben, mit einfacheren Möglichkeiten, die Informationen zu finden, und daher viel weniger Prozessaufrufen.

#!/bin/sh
xPATH=$(readlink -f -- "${1}")
for xFILE in "${xPATH}"/*; do
    [-d "${xFILE}"] && continue
    [! -r "${xFILE}"] && printf '"%s" is not readable.\n' "${xFILE}" 1>&2 && continue
    nLINKS=$(stat -c%h "${xFILE}")
    if [${nLINKS} -gt 1]; then
        iNODE=$(stat -c%i "${xFILE}")
        xDEVICE=$(stat -c%m "${xFILE}")
        printf '\nItem: %s[%d] = %s\n' "${xDEVICE}" "${iNODE}" "${xFILE}";
        find "${xDEVICE}" -inum ${iNODE} -not -path "${xFILE}" -printf ' -> %p\n' 2>/dev/null
    fi
done

Ich habe versucht, es Ihrem so ähnlich wie möglich zu halten, um einen einfachen Vergleich zu ermöglichen.

Kommentare zu diesem Skript und Ihrem

  • Man sollte die $IFS-Magie immer vermeiden, wenn ein glob ausreicht, da sie unnötig umständlich ist, und Dateinamen tatsächlich Zeilenumbrüche enthalten können (in der Praxis aber meist der erste Grund).

  • Sie sollten das manuelle Parsen von ls und solchen Ausgaben so weit wie möglich vermeiden, da es Sie früher oder später beißen wird. Zum Beispiel: in Ihrer ersten awk-Zeile scheitern Sie an allen Dateinamen, die Leerzeichen enthalten.

  • printf wird Ihnen am Ende oft Ärger ersparen, da es mit der %s-Syntax so robust ist. Es gibt Ihnen außerdem die volle Kontrolle über die Ausgabe und ist im Gegensatz zu echo auf allen Systemen konsistent.

  • stat kann Ihnen in diesem Fall eine Menge Logik ersparen.

  • GNU find ist leistungsstark.

  • Ihre head- und tail-Aufrufe hätten direkt in awk behandelt werden können, z. B. mit dem Befehl exit und/oder der Auswahl auf der NR-Variablen. Das würde Prozessaufrufe einsparen, was in hart arbeitenden Skripten fast immer die Performance stark verbessert.

  • Ihre egreps könnten genauso gut einfach grep sein.

2
2
2
2011-11-16 22:46:38 +0000

Basierend auf dem Skript findhardlinks (umbenannt in hard-links) habe ich das folgende Skript umstrukturiert, damit es funktioniert.

Ausgabe:

# ./hard-links /root

Item: /[10145] = /root/.profile
    -> /proc/907/sched
    -> /<some-where>/.profile

Item: /[10144] = /root/.tested
    -> /proc/907/limits
    -> /<some-where else>/.bashrc
    -> /root/.testlnk

Item: /[10144] = /root/.testlnk
    -> /proc/907/limits
    -> /<another-place else>/.bashrc
    -> /root/.tested

 

# cat ./hard-links
#!/bin/bash
oIFS="${IFS}"; IFS=$'\n';
xPATH="${1}";
xFILES="`ls -al ${xPATH}|egrep "^-"|awk '{print $9}'`";
for xFILE in ${xFILES[@]}; do
  xITEM="${xPATH}/${xFILE}";
  if [[! -r "${xITEM}"]] ; then
    echo "Path: '${xITEM}' is not accessible! ";
  else
    nLINKS=$(ls -ld "${xITEM}" | awk '{print $2}')
    if [${nLINKS} -gt 1]; then
      iNODE=$(ls -id "${xITEM}" | awk '{print $1}' | head -1l)
      xDEVICE=$(df "${xITEM}" | tail -1l | awk '{print $6}')
      echo -e "\nItem: ${xDEVICE}[$iNODE] = ${xITEM}";
      find ${xDEVICE} -inum ${iNODE} 2>/dev/null|egrep -v "${xITEM}"|sed 's/^/ -> /';
    fi
  fi
done
IFS="${oIFS}"; echo "";
1
1
1
2015-01-20 18:00:05 +0000

Eine GUI-Lösung kommt Ihrer Frage sehr nahe:

Sie können die tatsächlichen Hardlinks von “ls” nicht auflisten, weil die Datei-“Namen”, wie schon von anderen Kommentatoren erwähnt, nur Aliase auf dieselben Daten sind. Es gibt aber tatsächlich ein GUI-Tool, das dem, was Sie wollen, sehr nahe kommt, nämlich eine Pfadauflistung von Dateinamen, die auf dieselben Daten (als Hardlinks) zeigen, unter Linux anzuzeigen, es heißt FSLint. Die gewünschte Option finden Sie unter “Namenskonflikte” -> deaktivieren Sie “checkbox $PATH” in Search (XX) -> und wählen Sie “Aliases” aus der Dropdown-Box nach “for…” in der oberen Mitte.

FSLint ist sehr schlecht dokumentiert, aber ich habe herausgefunden, dass das Sicherstellen des eingeschränkten Verzeichnisbaums unter “Suchpfad” mit der aktivierten Checkbox für “Recurse?” und den oben genannten Optionen, eine Auflistung von fest verknüpften Daten mit Pfaden und Namen, die auf die gleichen Daten “zeigen”, erzeugt, nachdem das Programm sucht.

1
1
1
2017-12-06 17:34:25 +0000

Sie können ls so konfigurieren, dass Hardlinks mit einem “Alias” hervorgehoben werden, aber wie bereits erwähnt, gibt es keine Möglichkeit, die “Quelle” des Hardlinks anzuzeigen, weshalb ich .hardlink anhänge, um dabei zu helfen.

Fügen Sie das Folgende irgendwo in Ihrem .bashrc

alias ll='LC_COLLATE=C LS_COLORS="$LS_COLORS:mh=1;37" ls -lA --si --group-directories-first'
``` hinzu