Wie kann nur der Speicherplatz verwendet werden, der von Dateien belegt wird, die an keiner anderen Stelle fest verlinkt sind?

14

rsync --link-destWie kann ich anhand platzsparender Schnappschüsse herausfinden, wie viel Speicherplatz ich tatsächlich gespart habe? Oder allgemeiner:

Wie kann man herausfinden, wie viel Speicherplatz ein Verzeichnis belegt, wenn man nur Dateien berücksichtigt, die an keiner anderen Stelle außerhalb der Verzeichnisstruktur fest verlinkt sind? Anders gefragt: Wie viel Speicherplatz würde nach dem Löschen dieses Verzeichnisses tatsächlich freigegeben werden? ( du -hswürde lügen. Der Platz, der für die Hardlinks selbst benötigt wird, kann enthalten sein)

Tobias Kienzler
quelle
2
Standardmäßig zählt GNU dudie Dateigrößen nur einmal, auch wenn sie fest miteinander verknüpft sind, es sei denn, Sie verwenden die Option -l/ --count-links. Sie werden duzweimal mit und ohne diese Option auf dem gesamten Baum ausgeführt. Der Unterschied zwischen den Größen sollte darin bestehen, wie viel Speicherplatz Sie in allen Verzeichnissen gespeichert haben.
JW013

Antworten:

9

Vorausgesetzt, es gibt keine internen Hardlinks (dh jede Datei mit mehr als einem Hardlink ist von außerhalb des Baums verlinkt), können Sie Folgendes tun:

find . -links -2 -print0 | du -c --files0-from=-

BEARBEITEN Und hier ist, was ich in dem Kommentar skizziert habe, angewendet. Nur ohne du; Ein großes Lob an @StephaneChazelas für das Bemerken duist nicht erforderlich. Erklärung am Ende.

( find . -type d -printf '%k + ' ; \
  find . \! -type d -printf '%n\t%i\t%k\n' | \
    sort | uniq -c                         | \
    awk '$1 >= $2 { print $4 " +\\" }' ; \
  echo 0 ) | bc

Wir erstellen eine Zeichenfolge mit der Datenträgerverwendung (in KB) jeder relevanten Datei, die durch Pluszeichen getrennt ist. Dann füttern wir diese große Zugabe zu bc.

Der erste findAufruf erledigt das für Verzeichnisse.

Die zweite findOption gibt die Anzahl der Links, den Inode und die Festplattennutzung aus. Wir durchlaufen diese Liste sort | uniq -c, um eine Liste zu erhalten (Anzahl der Auftritte im Baum, Anzahl der Links, Inode, Festplattennutzung).

Wir durchlaufen diese Liste awkund drucken das vierte Feld, wenn das erste Feld (Anzahl der Erscheinungsbilder) größer oder gleich dem zweiten Feld (Anzahl der Hardlinks) ist, dh, es gibt keine Links zu dieser Datei von außerhalb des Baums. Datenträgernutzung) mit einem Pluszeichen und einem Backslash.

Schließlich geben wir a aus 0, damit die Formel syntaktisch korrekt ist (es würde +sonst en geben ) und übergeben sie an bc. Puh.

(Aber ich würde die einfachere erste Methode verwenden, wenn sie eine ausreichend gute Antwort liefert.)

angus
quelle
Danke, ja, wenn diese Voraussetzung erfüllt ist, funktioniert es. Aber was ist, wenn es nicht ist?
Tobias Kienzler
Das funktioniert nicht, da dies die Größe der Verzeichnisse selbst nicht berücksichtigt (die normalerweise mindestens 2 Links haben, und wenn dies nicht der Fall wäre, würden Sie die Dateien zweimal zählen lassen).
Stéphane Chazelas
1
Dann müsste findeine Liste aller Dateien mit ihren Inodes und der Anzahl der Links gedruckt werden. dann eine Kombination von sort | uniq -c, um zu ermitteln, wie oft jeder Inode im Baum erscheint, dann diejenigen mit einer Linkanzahl herauszufiltern, die größer als die Anzahl der Auftritte ist ... und dann diese Liste zu füttern du. Wenn die Anforderung jedoch erfüllt ist, sparen Sie den Aufwand.
Angus
@StephaneChazelas Es funktioniert, aber es ist wahr, dass es nicht die eigene Größe der Verzeichnisse berücksichtigt. Hätte nur dueinen -dähnlichen Parameter wie ls's ...
angus
Beachten Sie auch, dass auf btrfsDateisystemen immer die Anzahl der Links für Verzeichnisse angegeben ist. 1! -type d
Fügen Sie daher
5

Grundsätzlich müssen Sie die Inode-Nummern und die Anzahl der Verknüpfungen für alle Dateien (Nicht-Verzeichnisse) ermitteln, diese Anzahl der Verknüpfungen mit der Anzahl der Vorkommen der einzelnen Inodes vergleichen und die Datei ausschließen, wenn sie unterschiedlich sind.

Vorausgesetzt, sie befinden sich alle im selben Dateisystem, so etwas sollte funktionieren (mit GNU find):

find . -type d -printf '%k\n' -o -printf '%i %n %k\n' |
   awk '
     NF==1{t+=$0; next}
     {n1[$1]=$2; n2[$1]++; s[$1]=$3}
     END {
       for (i in n1)
         if (n1[i] == n2[i])
           t+=s[i]
       print t
     }'
Stéphane Chazelas
quelle
Ja, was ich gesagt habe (danke für die Gutschrift). Die zusätzliche Genauigkeit, die Sie durch das Zählen von Verzeichnissen erzielen, geht jedoch verloren, wenn Sie die ungenaue Datenträgernutzung hinzufügen.
Angus
@angus, was meinst du mit "ungenaue Datenträgernutzung"?
Stéphane Chazelas
Nichts, ich habe mich total geirrt %k. Das ist toll, duwird gar nicht benötigt! Ich werde meine Antwort aktualisieren, wenn ich nach Hause komme. Vielen Dank!
Angus
3

du Tatsächlich lügt es nicht;) Es analysiert die Verzeichnisse, die es gibt, wobei nur die ersten Hardlinks gezählt werden, die auf den gleichen Inode verweisen, auf den es stößt.

Wenn Sie fragen, duwas es nur in einem Verzeichnis sieht, ist es egal, dass es andere feste Links gibt, die auf den gleichen Inhalt verweisen:

$ du -h daily.0 && du -hc daily.1
29G /daily.0
29G /daily.1

Geben Sie nun dirs in dieselbe Zeile (beginnend mit der neuesten Zeile für inkrementelle rsync-Sicherungen mit --link-dest):

$ du -hc daily.0 daily.1
29G /daily.0
364M /daily.1
29G total

Oder das ganze Backup-Verzeichnis:

$ du -hc --max-depth=1 /snapshots
29G /daily.0
364M /daily.1
537M /daily.2
333M /daily.3
30G total

Alle Dateien in 'daily.1', die auf einen Inode verweisen (auch als "echte" Dateien bezeichnet), auf die bereits in 'daily.0' verwiesen wurde, werden nicht gezählt.

Das Löschen von daily.1 spart daher 364 MB auf Ihrem Gerät.

ENTFERNEN

tuk0z
quelle