Ich möchte rekursiv die größte Datei in jedem Verzeichnis finden

Ich möchte rekursiv die größte Datei in jedem Verzeichnis finden

Die Ausgabe enthält den Verzeichnisnamen, den Dateinamen und die Dateigröße. Eine (größte Datei) für jedes Verzeichnis, aus dem der Befehl ausgeführt wird.

Wenn möglich, auch die durchschnittliche Größe der Dateien in diesem Verzeichnis.

Der Zweck besteht darin, die Verzeichnisse nach Dateien zu durchsuchen, die viel größer sind als die anderen im Verzeichnis, damit sie ersetzt werden können

Antwort1

Sortieren Sie mit GNU findund sort( sed4.2.2 oder höher) einmal nach den Dateigrößen und dann noch einmal nach den Verzeichnispfaden:

find /some/dir -type f -printf '%s %f%h\0' | 
  sort -zrn |
  sort -zut/ -k2 |
  sed -zre 's: ([^/]*)(/.*): \2/\1:'

Erläuterung:

  • Die Dateigröße, der Name und der Pfad werden gedruckt (der erste durch ein Leerzeichen getrennt und die nächsten beiden durch /) und jeder Eintrag wird durch das ASCII-NUL-Zeichen abgeschlossen.
  • Anschließend sortieren wir numerisch anhand der Größe und gehen dabei von einer durch NUL getrennten Ausgabe aus (und in umgekehrter Reihenfolge, also zuerst die größten Dateien).
  • Dann sortdrucken wir nur die ersten eindeutigen Einträge und verwenden dabei alles aus dem zweiten /-getrennten Feld, das der Pfad zum Verzeichnis wäre, das die Datei enthält.
  • Anschließend sedtauschen wir die Verzeichnis- und Dateinamen, sodass wir einen normalen Pfad erhalten.

Für eine lesbare Ausgabe ersetzen Sie ASCII NUL durch Zeilenumbrüche:

find /some/dir -type f -printf '%s %f%h\0' | 
  sort -zrn |
  sort -zut/ -k2 |
  sed -zre 's: ([^/]*)(/.*): \2/\1:' |
  tr '\0' '\n'

Beispielausgabe:

$ find /var/log -type f -printf '%s %f%h\0' | sort -zrn | sort -zt/ -uk2 | sed -zre 's: ([^/]*)(/.*): \2/\1:' | tr '\0' '\n'
3090885 /var/log/syslog.1
39789 /var/log/apt/term.log
3968 /var/log/cups/access_log.1
31 /var/log/fsck/checkroot
467020 /var/log/installer/initial-status.gz
44636 /var/log/lightdm/seat0-greeter.log
15149 /var/log/lxd/lxd.log
4932 /var/log/snort/snort.log
3232 /var/log/unattended-upgrades/unattended-upgrades-dpkg.log

Antwort2

Durch die Kombination von findund awkkönnen auch Durchschnittswerte berechnet werden:

find . -type f -printf '%s %h/%f\0'|awk 'BEGIN { RS="\0" } { SIZE=$1; for (i = 1; i <= NF - 1; i++) $i = $(i + 1); NF = NF - 1; DIR=$0; gsub("/[^/]+$", "", DIR); FILE=substr($0, length(DIR) + 2); SUMSIZES[DIR] += SIZE; NBFILES[DIR]++; if (SIZE > MAXSIZE[DIR] || !BIGGESTFILE[DIR]) { MAXSIZE[DIR] = SIZE; BIGGESTFILE[DIR] = FILE } }; END { for (DIR in SUMSIZES) { printf "%s: average %f, biggest file %s %d\n", DIR, SUMSIZES[DIR] / NBFILES[DIR], BIGGESTFILE[DIR], MAXSIZE[DIR] } }'

Das AWK-Skript ist lesbarer gestaltet und

BEGIN { RS="\0" }

{
  SIZE=$1
  for (i = 1; i <= NF - 1; i++) $i = $(i + 1)
  NF = NF - 1
  DIR=$0
  gsub("/[^/]+$", "", DIR)
  FILE=substr($0, length(DIR) + 2)
  SUMSIZES[DIR] += SIZE
  NBFILES[DIR]++
  if (SIZE > MAXSIZE[DIR] || !BIGGESTFILE[DIR]) {
    MAXSIZE[DIR] = SIZE
    BIGGESTFILE[DIR] = FILE
  }
}

END {
  for (DIR in SUMSIZES) {
    printf "%s: average %f, biggest file %s %d\n", DIR, SUMSIZES[DIR] / NBFILES[DIR], BIGGESTFILE[DIR], MAXSIZE[DIR]
  }
}

Dies erwartet null-getrennte Eingabedatensätze (ich habe dies geklaut vonMurus Antwort); für jeden Eingabedatensatz

  • speichert die Größe (für spätere Verwendung),
  • entfernt alles vor dem ersten Zeichen im Pfad (damit wir zumindest Dateinamen mit Leerzeichen korrekt behandeln),
  • extrahiert das Verzeichnis,
  • extrahiert den Dateinamen,
  • addiert die zuvor gespeicherte Größe zur Summe der Größen im Verzeichnis,
  • erhöht die Anzahl der Dateien im Verzeichnis (so können wir den Durchschnitt berechnen),
  • Wenn die Größe größer als die gespeicherte Maximalgröße für das Verzeichnis ist oder wenn wir eine Datei im Verzeichnis noch nicht gesehen haben, werden die Informationen für die größte Datei aktualisiert.

Wenn das alles erledigt ist, durchläuft das Skript eine Schleife über die Schlüssel SUMSIZESund gibt das Verzeichnis, die durchschnittliche Größe, den Namen und die Größe der größten Datei aus.

Sie können die Ausgabe umleiten, sortum nach Verzeichnisnamen zu sortieren. Wenn Sie die Größen zusätzlich in benutzerfreundlicher Form formatieren möchten, können Sie die printfZeile ändern in

printf "%.2f %d %s: %s\n", SUMSIZES[DIR] / NBFILES[DIR], MAXSIZE[DIR], DIR, BIGGESTFILE[DIR]

und leiten Sie die Ausgabe dann an weiter numfmt --field=1,2 --to=iec. Sie können das Ergebnis weiterhin nach Verzeichnisnamen sortieren. Sie müssen lediglich beginnend mit dem dritten Feld sortieren: sort -k3.

Antwort3

Zsh'SPlatzhaltermusterwäre für die Art von Dingen, die Sie tun, sehr nützlich. Insbesondere kann zsh Dateien nach Attributen wie Typ, Größe usw. abgleichen durchGlob-Qualifikation. Glob-Qualifizierer ermöglichen auch das Sortieren der Spiele.

Beispielsweise wird in zsh *(.DOLN[1])zum Namen der größten Datei im aktuellen Verzeichnis erweitert. *ist das Muster für den Dateinamen (trifft auf alles zu, außer möglicherweise auf Dot-Dateien, abhängig von den Shell-Optionen). Der Qualifizierer .beschränkt die Übereinstimmungen auf reguläre Dateien, Dbewirkt , *dass Dot-Dateien eingeschlossen werden, OLsortiert nach abnehmender Größe („Länge“), Nbewirkt, dass die Erweiterung leer ist, wenn überhaupt keine übereinstimmende Datei vorhanden ist, und [1]wählt nur die erste Übereinstimmung aus.

Mit können Sie Verzeichnisse rekursiv aufzählen **/. Die folgende Schleife durchläuft beispielsweise alle Unterverzeichnisse des aktuellen Verzeichnisses und deren Unterverzeichnisse rekursiv:

for d in **/*(/); do … done

Sie könnenzstatum auf die Größe einer Datei und andere Metadaten zuzugreifen, ohne zum Parsen auf andere Tools angewiesen zu sein.

zmodload -F zsh/stat b:zstat
files=(*(DNoL))
zstat -A sizes +size -- $files
total=0; for s in $sizes; do total+=$s; done
if ((#sizes > 0)); then
  max=$sizes[-1]
  average=$((total/#sizes))
  median=$sizes[$((#sizes/2))]
fi

Antwort4

Versuchen Sie, Baobab oder ähnliche Software zu verwenden. Eine oder mehrere davon sind wahrscheinlich in Ihrer Distribution enthalten. Sie visualisieren die Problemverzeichnisse sehr gut.

  • Baobab
  • JDiskReport
  • ncdu
  • K4DirStat
  • QDirStat
  • GD-Karte

http://alternativeto.net/software/baobab/?platform=linux

Und auf der Manpage für Baobab steht, wie es ist.

$> man baobab
BAOBAB(1)

NAME
       Baobab - A graphical tool to analyse disk usage

SYNOPSIS
       baobab  [directory]

DESCRIPTION
       baobab is able to scan either specific folders or the whole filesys-
       tem (local and remote), in order to give the user a graphical tree
       representation including each directory size or percentage in the
       branch.  It also auto-detects in real-time any change made to your
       home directory as far as any mounted/unmounted device. A graphical
       treemap window is also provided for any selected folder.

       A detailed documentation on the program could be read at:
       http://www.gnome.org/projects/baobab

AUTHOR
       Fabio MARZOCCA <[email protected]>



                                                                     BAOBAB(1)

verwandte Informationen