Wie erhalte ich die tatsächliche Verzeichnisgröße (aus du heraus)?


17

Wie erhalte ich die tatsächliche Verzeichnisgröße mithilfe von UNIX / Linux-Standardtools?

Alternative Frage: Wie bekomme ich mich mir die aktuelle Verzeichnis Größe zu zeigen (nicht Festplattennutzung)?

Da Leute unterschiedliche Definitionen des Begriffs "Größe" zu haben scheinen: Meine Definition von "Verzeichnisgröße" ist die Summe aller regulären Dateien in diesem Verzeichnis.

Es ist mir egal, wie groß das Verzeichnis inode ist oder wie groß die Dateien auf dem jeweiligen Dateisystem sind (Blöcke * Blockgröße). Ein Verzeichnis mit 3 Dateien zu je 1 Byte hat eine Verzeichnisgröße von 3 Byte (nach meiner Definition).

Die Berechnung der Verzeichnisgröße mit du scheint unzuverlässig zu sein.
Zum Beispiel mkdir foo && du -b foomeldet "4096 foo", 4096 Bytes anstelle von 0 Bytes. Bei sehr großen Verzeichnissen kann die von gemeldete Verzeichnisgröße du -hsum 100 GB (!) Und mehr (komprimiertes Dateisystem) abweichen.

Also, was (Tool / Option) muss verwendet werden, um die tatsächliche Verzeichnisgröße zu erhalten?


Welches Dateisystem wird am neuen Speicherort verwendet - ist es xfszufällig?
Sergey Vlasov


Wenn es sich bei Ihrem neuen FS tatsächlich um XFS handelt, ist die stark erhöhte Datenträgerverwendung wahrscheinlich auf eine aggressive Vorbelegung zurückzuführen , die die Dateifragmentierung auf Kosten der Datenträgerverwendung verringert.
Sergey Vlasov

Antworten:


8

Hier ist ein Skript, das eine für Menschen lesbare Verzeichnisgröße mit Unix-Standardtools (POSIX) anzeigt.

#!/bin/sh
find ${1:-.} -type f -exec ls -lnq {} \+ | awk '
BEGIN {sum=0} # initialization for clarity and safety
function pp() {
  u="+Ki+Mi+Gi+Ti+Pi+Ei";
  split(u,unit,"+");
  v=sum;
  for(i=1;i<7;i++) {
    if(v<1024) break;
    v/=1024;
  }
  printf("%.3f %sB\n", v, unit[i]);
}
{sum+=$5}
END{pp()}'

z.B:

$ ds ~        
72.891 GiB

Und jetzt fand ich eine andere Option , die in allen vorgeschlagenen fehlt lshier Anrufungen: -q. Ohne diese Option bricht das Skript ab, wenn ein Dateiname Zeilenumbrüche enthält. Es ist zu schwierig, wirklich zuverlässige Shell-Skripte zu schreiben…
Sergey Vlasov

@SergeyVlasov Das Skript, das ich gepostet habe, sollte nicht mit solchen Dateien brechen, sondern nur die zusätzlichen Zeilen ignorieren. Der einzige Problemfall würde auftreten, wenn eine sorgfältig gestaltete Datei eine zusätzliche Zeile mit einem fünften Doppelpunkt enthält, die einen numerischen Wert enthält. Ihr Vorschlag würde diese Situation in der Tat vermeiden. Danke für den Tipp, Skript aktualisiert.
Juli

Hervorragende Antwort. +1 an Sie Sir
ehime

Dies ist eine der zuverlässigsten Lösungen. Es funktioniert mit Dateinamen, die Leerzeichen oder Anführungszeichen enthalten, und gibt eine für Menschen lesbare Größe aus.
basic6

@KIAaze Vielen Dank, dass Sie meinen Code überprüft und korrigiert haben!
Juli

8

Einige Versionen duunterstützen das Argument --apparent-size, dass die scheinbare Größe anstelle der Datenträgernutzung angezeigt wird. Ihr Befehl wäre also:

du -hs --apparent-size

Aus den in Ubuntu 12.04 LTS enthaltenen Manpages für du:

--apparent-size
      print apparent sizes,  rather  than  disk  usage;  although  the
      apparent  size is usually smaller, it may be larger due to holes
      in (`sparse') files, internal  fragmentation,  indirect  blocks,
      and the like

1
funktioniert nicht: Leerzeichen melden
Karl Forner

1
das hat bei mir funktioniert.
Connorbode

2
Beim Vergleich von Verzeichnissen in verschiedenen Dateisystemen ergeben sich erheblich unterschiedliche Größen. Zum Beispiel hat derselbe Ordner eine scheinbare Größe von 290 GB auf dem ZFS-Dateisystem und 324 GB exFat. Die obigen Lösungen ergeben die gleiche Größe.
Pixus.ru

4

Nur eine Alternative mit ls:

ls -nR | grep -v '^d' | awk '{total += $5} END {print total, "Total"}'

ls -nR: -nwie -l, aber numerische UIDs und GIDs auflisten und -RUnterverzeichnisse rekursiv auflisten .

grep -v:Invertieren Sie den Übereinstimmungssinn, um nicht übereinstimmende Linien auszuwählen. (-v wird von POSIX angegeben.) '^ d'schließt die Verzeichnisse aus.

Ls-Befehl: http://linux.about.com/od/commands/l/blcmdl1_ls.htm

Man Grep: http://linux.die.net/man/1/grep

EDIT :

Bearbeitet als Vorschlag @ Sergey Vlasov.


Mit Hilfe der -nOption für lsstatt -l(show UID / GID - Nummern statt Namen) ist sicherer, weil Benutzer- und Gruppennamen Leerzeichen enthalten können (zB wenn winbindoder sssdverwendet wird , um das System zu einer Windows - Domäne beitreten, können Sie Gruppennamen erhalten wie domain users) . Es sollte auch schneller sein, da Benutzer- und Gruppennamen nicht gesucht werden müssen.
Sergey Vlasov

Danke, das ist VIEL schneller als find -exec ls!
gpothier

4

Angenommen, Sie haben duGNU coreutils, dann sollte dieser Befehl die scheinbare Gesamtgröße einer beliebigen Anzahl von regulären Dateien in einem Verzeichnis berechnen, ohne die Anzahl der Dateien zu beschränken:

find . -type f -print0 | du -scb --files0-from=- | tail -n 1

Fügen Sie die -lOption hinzu, duwenn einige fest verknüpfte Dateien enthalten sind und Sie jeden Hardlink separat zählen möchten (standardmäßig werden dumehrere Hardlinks nur einmal gezählt).

Der wichtigste Unterschied zu plain du -sbist, dass recursive duauch die Größe von Verzeichnissen zählt, die von verschiedenen Dateisystemen unterschiedlich gemeldet werden. Um dies zu vermeiden, wird der findBefehl verwendet, um nur reguläre Dateien an zu übergeben du. Ein weiterer Unterschied besteht darin, dass Symlinks ignoriert werden (wenn sie gezählt werden sollen, muss der findBefehl angepasst werden).

Dieser Befehl wird verbrauchen auch mehr Speichers als schlicht du -sb, weil die Verwendung von --files0-from=FILEMarken duSpeicher Gerät und Inode - Nummern von allen bearbeiteten Dateien, wie auf das Standardverhalten gegenüber von nur Dateien mit mehr als einem harten Link zu erinnern. (Dies ist kein Problem, wenn die -lOption zum mehrmaligen Zählen von Hardlinks verwendet wird, da der einzige Grund zum Speichern von Geräte- und Inode-Nummern darin besteht, bereits verarbeitete Hardlink-Dateien zu überspringen.)

Wenn Sie eine lesbare Darstellung der Gesamtgröße erhalten möchten, fügen Sie einfach die -hOption hinzu (dies funktioniert, weil dunur einmal aufgerufen wird und die Gesamtgröße selbst berechnet wird, im Gegensatz zu einigen anderen vorgeschlagenen Antworten):

find . -type f -print0 | du -scbh --files0-from=- | tail -n 1

oder (wenn Sie befürchten, dass einige Effekte von -bdann überschrieben werden -h)

find . -type f -print0 | du -sc --apparent-size -h --files0-from=- | tail -n 1

Ich bin nicht sicher, was ich für FreeBSD tun soll - obwohl -bdies wahrscheinlich durch ersetzt werden könnte -A -B 1, gibt es kein Äquivalent für --files0-from=-und für die Verwendung xargssind einige Problemumgehungen erforderlich, falls die Dateiliste größer ist als ARG_MAX(und eine externe Lösung für vom Menschen lesbare Ausgaben).
Sergey Vlasov

3

Wenn alles, was Sie wollen, die Größe der Dateien ist, mit Ausnahme des Speicherplatzes, den die Verzeichnisse belegen, können Sie so etwas tun

find . -type f -print0 | xargs -0 du -scb | tail -n 1

@ SergeyVlasov wies darauf hin, dass dies fehlschlagen wird, wenn Sie mehr Dateien als haben argmax. Um dies zu vermeiden, können Sie Folgendes verwenden:

find . -type f -exec du -sb '{}' \; | gawk '{k+=$1}END{print k}'

1
Dieser Befehl gibt im Hintergrund ein falsches Ergebnis aus, wenn das Verzeichnis so viele Dateien enthält, dass sie nicht in das Limit für die Größe von execve () - Argumenten passen. In diesem Fall xargswird er dumehrmals aufgerufen und jeder Aufruf gibt die Gesamtsumme nur für seinen Teil aus In der gesamten Dateiliste wird dann tailnur die Gesamtgröße des letzten Teils angezeigt.
Sergey Vlasov

1
@SergeyVlasov guter Punkt, ich hatte nicht daran gedacht, danke, Antwort aktualisiert.
Terdon
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.