Frage

Gibt es eine Methode in Linux die Anzahl der Dateien in einem Verzeichnis zu berechnen (die unmittelbaren Kinder) in O (1) (unabhängig von der Anzahl der Dateien), ohne zuerst das Verzeichnisses zur Liste mit? Wenn nicht O (1), ist es eine ziemlich effiziente Weise?

Ich bin für eine Alternative zu ls | wc -l suchen.

War es hilfreich?

Lösung

readdir ist nicht so teuer wie Sie vielleicht denken. Der Kniff ist zu vermeiden stat'ing jede Datei, und (optional) die Ausgabe von ls zu sortieren.

/bin/ls -1U | wc -l

vermeidet Aliase in Ihrem Shell, nicht sortierte die Ausgabe und Listen 1 Datei pro Zeile (nicht unbedingt notwendig, wenn die Ausgabe in WC kochend).

Die ursprüngliche Frage kann umformuliert werden „funktioniert die Datenstruktur eines Verzeichnisspeicher eine Zählung der Anzahl der Einträge?“, Zu dem die Antwort nein ist. Es gibt keine effizientere Art von Dateien als readdir Zählen (2) / getdents (2).

Andere Tipps

kann man die Anzahl der Unterverzeichnisse eines bestimmten Verzeichnisses erhalten, ohne die ganze Liste durchlaufen von stat'ing (stat (1) oder stat (2)) das angegebene Verzeichnis und Beobachten der Anzahl der Links zu diesem Verzeichnis. Ein bestimmtes Verzeichnis mit N geordneten Verzeichnissen einen Link Zahl von N + 2 hat, eine Verbindung für den Eintrag „..“ jedes Unterverzeichnis, plus zwei für die „“ und „..“ Einträge des angegebenen Verzeichnisses.

Allerdings kann man nicht die Anzahl aller Dateien erhalten (ob normale Dateien oder Unterverzeichnisse), ohne die ganze Liste durchlaufen -. Das ist richtig

Die "/ bin / ls -1U" Befehl werden alle Einträge jedoch nicht erhalten. Es wird noch nur diese Verzeichniseinträge, die (.) Zeichen nicht mit dem Punkt beginnen. Zum Beispiel wäre es nicht zählen die „.profile“ Datei in vielen Login $ HOME Verzeichnisse gefunden.

Man kann entweder die "/ bin / ls -f" Befehl oder die "/ bin / ls -Ua" Befehl verwenden, um die Art zu vermeiden und alle Einträge bekommen.

Vielleicht leider für Ihre Zwecke, entweder die „/ bin / ls -f“ Befehl oder die „/ bin / ls -Ua“ Befehl wird auch die zählen „“ und „..“ Einträge, die in jedem Verzeichnis sind. Sie werden 2 von der Zählung subtrahieren müssen zu vermeiden, dass diese beiden Einträge zu zählen, wie im folgenden Beispiel:

expr `/bin/ls -f | wc -l` - 2     # Those are back ticks, not single quotes.

Die --format = einspaltig (-1) Option ist nicht notwendig, auf dem "/ bin / ls -Ua" -Befehl, wenn die "ls" Ausgangsleitungen, wie in zu "WC" in diesem Fall. Der „ls“ Befehl wird die Ausgabe automatisch in einer einzigen Spalte schreiben, wenn der Ausgang keinen Terminal ist.

Die -U Option für ls ist nicht in POSIX und in OS X ls hat es eine andere Bedeutung von GNU ls, das ist, dass es -t und -l habendes Zeiten statt Änderungszeiten macht. -f ist in POSIX als XSI Erweiterung. Das Handbuch von GNU ls beschreibt -f als do not sort, enable -aU, disable -ls --color und -U als do not sort; list entries in directory order.

POSIX beschreibt -f wie folgt aus:

Kraft jedes Argument als Verzeichnis und die Liste der in jedem Schlitz gefunden Name interpretiert werden. Diese Option wird deaktivieren -l, -t, -s und -r und wird eingeschaltet -a; die Reihenfolge ist die Reihenfolge, in der Einträge im Verzeichnis angezeigt werden.

Befehle wie ls|wc -l das falsche Ergebnis geben, wenn Dateinamen Zeilenumbrüche enthalten.

In zsh Sie etwas tun können:

a=(*(DN));echo ${#a}

D (glob_dots) enthält Dateien, dessen Namen beginnt mit einem Punkt und N (null_glob) bewirkt, dass der Befehl nicht in einem leeren Verzeichnis zu einem Fehler führen.

oder das gleiches in bash:

shopt -s dotglob nullglob;a=(*);echo ${#a[@]}

Wenn IFS ASCII Ziffern enthält, fügen Sie doppelte Anführungszeichen um ${#a[@]}. In shopt -u failglob um sicherzustellen, dass failglob nicht gesetzt ist.

Eine tragbare Option ist die Verwendung find:

find . ! -name . -prune|grep -c /

grep -c / kann mit wc -l ersetzt werden, wenn Dateinamen Zeilenumbrüche nicht enthalten. ! -name . -prune ist eine tragbare Alternative zu -mindepth 1 -maxdepth 1.

Oder hier ist eine andere Alternative, die in der Regel keine Dateien enthalten, deren Name beginnt mit einer Periode:

set -- *;[ -e "$1" ]&&echo "$#"

Der obige Befehl enthält jedoch Dateien, deren Name beginnt mit einer Periode, wenn eine Option wie dotglob in bash oder glob_dots in zsh gesetzt. Wenn * Spiele keine Datei, den Befehl zu einem Fehler in zsh mit den Standardeinstellungen.

habe ich diese command..works wie ein charm..only die maxdepth..that Unter ist Verzeichnisse zu ändern

find * -maxdepth 0 -type d -exec sh -c "echo -n {} ' ' ; ls -lR {} | wc -l" \;

Ich glaube, du mehr Kontrolle über diesen mit find haben:

find <path> -maxdepth 1 -type f -printf "." | wc -c
  • find -maxdepth 1 nicht tiefer in die Hierarchie der Dateien gehen.
  • -type f können nur Dateien zu filtern. Ebenso können Sie -type d für Verzeichnisse verwendet werden.
  • -printf "." druckt einen Punkt für jedes Spiel.
  • wc -c zählt die Zeichen, so dass er die Punkte zählt der print erstellt ... die Zähleinrichtungen, wie viele Dateien in dem angegebenen Pfad vorhanden sind.

Soweit ich weiß, gibt es keine bessere Alternative. Diese Information könnte seinen Wegthema auf diese Frage und Sie können bereits wissen, dass unter Linux (im allgemeinen unter Unix) Verzeichnisse nur spezielle Datei sind, die die Liste der anderen Dateien enthalten (Ich verstehe, dass die genauen Details zu spezifischer Datei abhängig sind System, aber das ist die allgemeine Idee). Und es gibt keinen Anruf die Gesamtzahl der Einträge zu finden, ohne die ganze Liste durchlaufen. Bitte stellen Sie mich korrigieren, wenn ich falsch liege.

Für die Anzahl aller Datei in einem aktuellen Verzeichnis versuchen Sie dies:

ls -lR * | wc -l

Verwendung ls -1 | wc -l

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top