Suchen Sie nach Verzeichnissen, die eine bestimmte Anzahl von Dateien enthalten

13

Ich hatte gehofft, dass ich dies mit dem findBefehl tun kann, aber ich kann im Handbuch keinen Test dafür sehen, was ich will. Ich möchte in der Lage sein, alle Verzeichnisse im Arbeitsverzeichnis zu finden, die weniger als, mehr als oder genau die von mir angegebene Anzahl enthalten.

find . -filecount +10 # any directory with more than 10 entries
find . -filecount 20 # any directory with exactly 20 entries

Aber leider gibt es keine solche Option.

Paul Ruane
quelle
versuchen Sie etwas wie "ls -al | wc -l | grep"
Vanadis

Antworten:

16

Sie können dies versuchen, um die Namen der Unterverzeichnisse und die Anzahl der darin enthaltenen Dateien / Verzeichnisse abzurufen:

find . -maxdepth 1 -type d -exec bash -c "echo -ne '{} '; ls '{}' | wc -l" \;

Wenn Sie dasselbe für alle Unterverzeichnisse tun möchten (rekursive Suche), verwenden Sie stattdessen Folgendes:

find . -type d -exec bash -c "echo -ne '{} '; ls '{}' | wc -l" \;

So wählen Sie die Verzeichnisse mit genau 10 Dateien aus:

find . -maxdepth 1 -type d -exec bash -c "echo -ne '{} '; ls '{}' | wc -l" \; | 
  awk '$NF==10'

10 oder mehr:

find . -maxdepth 1 -type d -exec bash -c "echo -ne '{} '; ls '{}' | wc -l" \; | 
 awk '$NF>=10'

10 oder weniger:

find . -maxdepth 1 -type d -exec bash -c "echo -ne '{} '; ls '{}' | wc -l" \; | 
 awk '$NF<=10'

Wenn Sie nur den Verzeichnisnamen behalten möchten (z. B. wenn Sie ihn an einen anderen Prozess weiterleiten möchten, wie von @evilsoup vorgeschlagen), können Sie Folgendes verwenden:

find . -maxdepth 1 -type d -exec bash -c "echo -ne '{}\t'; ls '{}' | wc -l" \; | 
 awk -F"\t" '$NF<=10{print $1}'
Terdon
quelle
1
Ich denke, es könnte nützlich sein, den Befehl awk einzuschließen, um die Anzahl der Dateien zu verringern (dh die letzte durch Leerzeichen getrennte Spalte), falls der Fragesteller die Ausgabe an etwas anderes weiterleiten möchte.
Evilsoup
1
@evilsoup gute Idee, fertig.
Terdon
Unterstützung von Leerzeichen und Sonderzeichen in den Verzeichnisnamen; Versuchen Sie, die Verwendung von einfachen und doppelten Anführungszeichen als solche umzukehren:find . -type d -exec bash -c 'echo -ne "{} "; ls "{}" | wc -l' \; | awk '$NF<=10'
Håvard Geithus
3

Auflisten von unmittelbaren Unterverzeichnissen, die genau $NUM Dateien enthalten.

find -maxdepth 2 -mindepth 2 -type f -printf '%h\0' | awk -v num="$NUM" 'BEGIN{RS="\0"} {array[$0]++} END{for (line in array) if (array[line]==num) printf "%s\n", line}'

Zum Auflisten von unmittelbaren Unterverzeichnissen, die mehr als $NUMDateien enthalten.

find -maxdepth 2 -mindepth 2 -type f -printf '%h\0' | awk -v num="$NUM" 'BEGIN{RS="\0"} {array[$0]++} END{for (line in array) if (array[line]>num) printf "%s\n", line}'

Zum Auflisten von unmittelbaren Unterverzeichnissen, die weniger als $NUMDateien enthalten.

find -maxdepth 2 -mindepth 2 -type f -printf '%h\0' | awk -v num="$NUM" 'BEGIN{RS="\0"} {array[$0]++} END{for (line in array) if (array[line]<num) printf "%s\n", line}'

Elemente werden durch ein Nullzeichen abgeschlossen \0, sodass Dateinamen, die Zeilenumbrüche oder andere Arten von Leerzeichen enthalten, korrekt interpretiert werden. Das %hdruckt jede Datei dirname. awkVerwendet dann ein Array, um zu zählen, wie oft es auf jedes Verzeichnis trifft, und druckt es, wenn die Bedingungen erfüllt sind.

Bitte beachten Sie, dass keiner der oben genannten Befehle Verzeichnisse anzeigt, die keine Dateien enthalten. Beachten Sie auch, dass ich mich mit Datei auf reguläre Dateien beziehe, nicht auf Links, Verzeichnisse, Sockets, Blöcke, Named Pipes usw.

Ich habe versucht, dies so einfach wie möglich zu machen. Wenn Sie rekursive Unterverzeichnisse oder die darin enthaltenen Dateien suchen möchten, ist ein geänderter Befehl erforderlich. Es gibt zu viele Möglichkeiten, sie alle aufzulisten.

Sechs
quelle
2

Versuche dies:

[`finden. | wc -l` -eq 10] && echo "Gefunden"

[`finden. | wc -l` -gt 10] && echo "Gefunden"

[`finden. | wc -l` -lt 10] && echo "Gefunden"

In diesen Beispielen können Sie überprüfen, ob das CURRENT-Verzeichnis genau 10, mehr als 10 und weniger als 10 Dateien / Verzeichnisse enthält. Wenn Sie eine Reihe von Verzeichnissen überprüfen müssen, verwenden Sie einfach loop.

September
quelle
Ihre Lösung zählt auch das aktuelle Verzeichnis ( .), das Sie möglicherweise entsprechend ändern möchten.
Terdon
Ich mag die Ausrichtung dieser Antwort (weil ich ein Vielfraß bin, wenn es darum geht , Dinge in der Shell zu erledigen), aber Sie sollten besser wc -l < <(printf %s\\n ./*)oder printf %s\\n ./* | wc -linnerhalb des Tests arbeiten, um einen unnötigen findAnruf zu vermeiden . Dadurch wird auch das von @terdon festgestellte Problem vermieden, .in das Ergebnis aufgenommen zu werden. Es würde jedoch auch auf das Problem stoßen, Dateien zu ignorieren, die mit a beginnen .; Ich würde dies mit lösen shopt -s dotglob(damit Globs mit Dateien übereinstimmen, die mit a beginnen ., aber nicht .oder ..).
Evilsoup
@terdon Es ist nicht wichtig. Es ist keine endgültige Lösung, nur ein Beispiel, eine Idee. Sie können -1 oder 10 bis 11 in der endgültigen Version ändern.
September
Ich weiß, und die Idee ist gut, deshalb habe ich den Vorschlag gemacht.
Terdon
@ Terdon. Vielen Dank. Es kann viele verschiedene Anforderungen geben, z. B.: Zählen Sie nur Dateien, nicht jedoch Verzeichnisse, Links oder feste Links. Dateien in Unterverzeichnissen zählen oder nicht. Zähle versteckte Dateien (wie .bashrc) ... ... damit dein Ausdruck sehr lang sein kann. :)
September