Finden Sie die ältesten Dateien / Verzeichnisse im Dateisystem mit bis zu 50 TB

8

Ich muss die ältesten Dateien mit den zugehörigen Verzeichnissen in einem 90-TB-Dateisystem mit bis zu 50 TB finden und sie dann in ein anderes Dateisystem verschieben. Sie müssen ihre Verzeichnisstruktur beibehalten, da dies die Dateien identifiziert. Damit -

erste Ebene / zweite Ebene / dritte Ebene / (Datei)

ist die Struktur. Ich muss die gesamte Struktur verschieben - es gibt nichts in den Verzeichnissen der obersten Ebene, aber ohne sie kann ich nicht identifizieren, zu was die Datei gehört, da alle Dateien, die ich suche, denselben Namen haben. Wenn der Vorgang abgeschlossen ist, sollte ich ungefähr 40 TB im ursprünglichen Dateisystem übrig haben und fast nichts im neuen Dateisystem übrig haben, da die ältesten Dateien im Original jetzt da sind.

Vielen Dank!

J Telep
quelle

Antworten:

9

Mit GNU-Tools und rsynckönnen Sie Folgendes tun:

export LC_ALL=C # force tools to regard those file paths as arrays
                # of bytes (as they are in effect) and not do fancy
                # sorting (and use English for error/warning messages 
                # as an undesired side effect).

find . -type f -printf '%T@/%s/%p\0' | # print mtime/size/path
  sort -zn | # numerical sort, oldest first
  awk -v RS='\0' -v ORS='\0' -F / -v max=50e12 '
    {total_size += $2}
    total_size > max {exit}
    {
      sub("^[^/]*/[^/]*/", "") # remove mtime/size/
      print # path
    }' |
  rsync -nv -aHAX0 --files-from=- --remove-source-files . /dest/dir/

(ungetestet. Das -nist für Trockenlauf. Entfernen, wenn glücklich).

Beachten Sie, dass wir die kumulative Dateigröße basierend auf den Dateigrößen berechnen ( %sdurch %bdie Datenträgerverwendung in Sektoren ersetzen (und zu ändern total_size += $2 * 512) und Hardlinks ignorieren. Diese Dateien werden beim Kopieren in das Zieldateisystem zusammen mit den Verzeichnissen verwendet Diese enthalten wahrscheinlich mehr als 50 TB (es sei denn, es wird eine Dateisystemkomprimierung oder -deduplizierung durchgeführt).

Stéphane Chazelas
quelle
1
Bessere Antwort als meine Antwort (obwohl ich total_size > max { exit 0 }dem awk-Skript eine hinzugefügt hätte )
symcbean
@symcbean, guter Punkt! Ich habe es jetzt hinzugefügt. Vielen Dank.
Stéphane Chazelas
Das sieht gut aus !! Eine Frage: Ich gehe davon aus, dass der Teil "max = 50e12" der awk-Anweisung dem System vorschreibt, dass wir 50 TB möchten, also basierend auf zusätzlichen Ordnern (da es zwei für jede Datei gibt), wenn ich es reduzieren müsste dass "50" bis "49" und das würde 49 TB entsprechen?
J Telep
1
@JTelep, das ist wissenschaftliche Notation. 50e12 ist 50 mal 10 hoch 12, also 50 TB (nicht 50 TB, für die Sie benötigen würden 50 * 2^40). Sie können es auch dahingehend ändern, total_size += $2 + overheadwo overheadder Overhead definiert ist, der diesen Ordnern entsteht. Siehe auch %kanstatt %sdie Festplattennutzung in KiB abzurufen.
Stéphane Chazelas
2

Der Befehl 'ls' ist mit Zeitstempeln etwas kreativ - daher kann das Parsen schmerzhaft sein. Es wäre wahrscheinlich viel einfacher, dies in einer Sprache zu implementieren, die stat () implementiert . Einige Unix-Versionen verfügen über eine Befehlszeilenstatistik - auf einer nahe gelegenen RH-Box:

 find ${BASEDIR} -type f -exec stat --format="%y %b %n" {} \; | sort | less

Aber das läuft wie ein Hund mit einer großen Anzahl von Dateien.

Die Dokumentation für GNU awk enthält eine Beispielerweiterung mit Dateisystemfunktionen. Sie müssen jedoch einige Arbeiten ausführen, um diese zu erstellen und zu warten.

Das Schreiben eines Programms von Grund auf in PHP, C oder Perl (oder go, ruby ​​oder vielen anderen Sprachen) wäre unkompliziert, würde jedoch den Rahmen eines Beitrags hier sprengen.

symcbean
quelle
1
Beachten Sie, dass das GNU statlang wurde hinzugefügt , nachdem GNU findeinen hatte -printfBefehl (das die gleichen wie GNU tun kann , statmit einer viel besseren Schnittstelle).
Stéphane Chazelas