So durchlaufen Sie einen Verzeichnisbaum unter Linux

Veröffentlicht: 2022-07-21
Linux-Laptop mit einer Bash-Eingabeaufforderung
fatmawati achmad zaenuri/Shutterstock.com

Mit Verzeichnissen unter Linux können Sie Dateien in verschiedenen, separaten Sammlungen gruppieren. Der Nachteil ist, dass es mühsam wird, von Verzeichnis zu Verzeichnis zu wechseln, um eine sich wiederholende Aufgabe auszuführen. So automatisieren Sie das.

Alles über Verzeichnisse

Der erste Befehl, den Sie lernen, wenn Sie in Linux eingeführt werden, ist wahrscheinlich ls , aber cd wird nicht weit dahinter liegen. Verzeichnisse zu verstehen und sich darin zu bewegen, insbesondere verschachtelte Unterverzeichnisse, ist ein grundlegender Teil des Verständnisses, wie Linux sich selbst organisiert und wie Sie Ihre eigene Arbeit in Dateien, Verzeichnisse und Unterverzeichnisse organisieren können.

Die Linux-Verzeichnisstruktur, erklärt
RELATED Die Linux-Verzeichnisstruktur, erklärt

Das Konzept eines Verzeichnisbaums zu verstehen – und wie man sich zwischen ihnen bewegt – ist einer der vielen kleinen Meilensteine, die Sie passieren, wenn Sie sich mit der Landschaft von Linux vertraut machen. Wenn Sie cd mit einem Pfad verwenden, gelangen Sie zu diesem Verzeichnis. Shortcuts wie cd ~ oder cd allein bringen Sie zurück in Ihr Home-Verzeichnis, und cd .. bringt Sie im Verzeichnisbaum eine Ebene nach oben. Einfach.

Es gibt jedoch keine ebenso einfache Möglichkeit, einen Befehl in allen Verzeichnissen eines Verzeichnisbaums auszuführen. Es gibt verschiedene Möglichkeiten, wie wir diese Funktionalität erreichen können, aber es gibt keinen Standard-Linux-Befehl, der diesem Zweck gewidmet ist.

Einige Befehle wie ls haben Befehlszeilenoptionen, die sie dazu zwingen, rekursiv zu arbeiten, was bedeutet, dass sie in einem Verzeichnis beginnen und sich methodisch durch den gesamten Verzeichnisbaum unterhalb dieses Verzeichnisses arbeiten. Für ls ist es die Option -R (rekursiv).

Wenn Sie einen Befehl verwenden müssen, der keine Rekursion unterstützt, müssen Sie die rekursive Funktionalität selbst bereitstellen. Hier ist, wie das geht.

VERWANDT: 37 Wichtige Linux-Befehle, die Sie kennen sollten

Der Baumbefehl

Der tree wird uns bei der vorliegenden Aufgabe nicht helfen, aber er macht es einfach, die Struktur eines Verzeichnisbaums zu sehen. Es zeichnet den Baum in einem Terminalfenster, sodass wir einen sofortigen Überblick über die Verzeichnisse und Unterverzeichnisse erhalten, aus denen der Verzeichnisbaum besteht, und ihre relativen Positionen im Baum.

Sie müssen tree installieren.

Unter Ubuntu müssen Sie Folgendes eingeben:

 sudo apt Baum installieren 

Baum auf Ubuntu installieren

Verwenden Sie auf Fedora:

 sudo dnf Baum installieren 

Baum auf Fedora installieren

Auf Manjaro lautet der Befehl:

 sudo pacman -Sy-Baum 

Baum auf Manjaro installieren

Die Verwendung von tree ohne Parameter zeichnet den Baum unterhalb des aktuellen Verzeichnisses.

 Baum 

Laufender Baum im aktuellen Verzeichnis

Sie können einen Pfad zum tree in der Befehlszeile übergeben.

 Baumarbeit 

Baum in einem angegebenen Verzeichnis ausführen

Die Option -d (Verzeichnisse) schließt Dateien aus und zeigt nur Verzeichnisse an.

 Baum -d Arbeit 

Laufender Baum und nur Verzeichnisse anzeigen

Dies ist der bequemste Weg, um sich einen klaren Überblick über die Struktur eines Verzeichnisbaums zu verschaffen. Der hier gezeigte Verzeichnisbaum wird in den folgenden Beispielen verwendet. Es gibt fünf Textdateien und acht Verzeichnisse.

Analysieren Sie die Ausgabe von ls nicht, um Verzeichnisse zu durchsuchen

Ihr erster Gedanke könnte sein, wenn ls einen Verzeichnisbaum rekursiv durchlaufen kann, warum nicht ls verwenden, um genau das zu tun und die Ausgabe in einige andere Befehle zu leiten, die die Verzeichnisse parsen und einige Aktionen ausführen?

Das Analysieren der Ausgabe von ls gilt als schlechte Praxis. Aufgrund der Fähigkeit von Linux, Datei- und Verzeichnisnamen zu erstellen, die alle möglichen seltsamen Zeichen enthalten, wird es sehr schwierig, einen generischen, universell korrekten Parser zu erstellen.

Möglicherweise erstellen Sie niemals wissentlich einen so absurden Verzeichnisnamen, aber ein Fehler in einem Skript oder einer Anwendung könnte dies tun.

Ein bizarrer Verzeichnisname

Das Parsen legitimer, aber schlecht durchdachter Datei- und Verzeichnisnamen ist fehleranfällig. Es gibt andere Methoden, die wir verwenden können, die sicherer und viel robuster sind, als sich auf die Interpretation der Ausgabe von ls zu verlassen.

Verwenden des Find-Befehls

Der Befehl find hat eingebaute rekursive Fähigkeiten und kann auch Befehle für uns ausführen. Auf diese Weise können wir leistungsstarke Einzeiler erstellen. Wenn es etwas ist, das Sie wahrscheinlich in Zukunft verwenden möchten, können Sie Ihren Einzeiler in einen Alias ​​oder eine Shell-Funktion umwandeln.

Dieser Befehl durchläuft rekursiv den Verzeichnisbaum und sucht nach Verzeichnissen. Jedes Mal, wenn es ein Verzeichnis findet, gibt es den Namen des Verzeichnisses aus und wiederholt die Suche innerhalb dieses Verzeichnisses. Nachdem das Durchsuchen eines Verzeichnisses abgeschlossen ist, verlässt es dieses Verzeichnis und nimmt die Suche in seinem übergeordneten Verzeichnis wieder auf.

 find work -type d -execdir echo "In:" {} \; 

Verwenden des Befehls find zum rekursiven Suchen von Verzeichnissen

Sie können anhand der Reihenfolge, in der die Verzeichnisse aufgelistet sind, sehen, wie die Suche durch den Baum fortschreitet. Indem Sie die Ausgabe des Befehls tree mit der Ausgabe des find vergleichen, sehen Sie, wie find jedes Verzeichnis und jedes Unterverzeichnis der Reihe nach durchsucht, bis es auf ein Verzeichnis ohne Unterverzeichnisse trifft. Es geht dann eine Ebene zurück und nimmt die Suche auf dieser Ebene wieder auf.

So setzt sich der Befehl zusammen.

  • find : Der find Befehl.
  • work : Das Verzeichnis, in dem die Suche gestartet werden soll. Dies kann ein Pfad sein.
  • -type d : Wir suchen nach Verzeichnissen.
  • -execdir : Wir werden in jedem Verzeichnis, das wir finden, einen Befehl ausführen.
  • echo „In:“ {} : Dies ist der Befehl. Wir geben einfach den Namen des Verzeichnisses an das Terminalfenster zurück. Das „{}“ enthält den Namen des aktuellen Verzeichnisses.
  • \; : Dies ist ein Semikolon, das zum Beenden des Befehls verwendet wird. Wir müssen es mit dem Backslash maskieren, damit Bash es nicht direkt interpretiert.

Mit einer kleinen Änderung können wir den Befehl find dazu bringen, Dateien zurückzugeben, die mit einem Suchhinweis übereinstimmen. Wir müssen die Option -name und einen Suchhinweis einfügen. In diesem Beispiel suchen wir nach Textdateien, die mit „*.txt“ übereinstimmen, und geben ihren Namen an das Terminalfenster zurück.

 find work -name "*.txt" -type f -execdir echo "Found:" {} \; 

Verwenden des find-Befehls zum rekursiven Suchen von Dateien

Ob Sie nach Dateien oder Verzeichnissen suchen, hängt davon ab, was Sie erreichen möchten. Um einen Befehl in jedem Verzeichnis auszuführen, verwenden -type d . Um einen Befehl für jede übereinstimmende Datei auszuführen, verwenden -type f .

Dieser Befehl zählt die Zeilen in allen Textdateien im Startverzeichnis und Unterverzeichnissen.

 find work -name "*.txt" -type f -execdir wc -l {} \; 

Verwenden von find mit dem Befehl wc

VERWANDT: So verwenden Sie den Find-Befehl unter Linux

Durchsuchen von Verzeichnisbäumen mit einem Skript

Wenn Sie Verzeichnisse innerhalb eines Skripts durchsuchen müssen, können Sie den Befehl find in Ihrem Skript verwenden. Wenn Sie die rekursiven Suchen selbst durchführen müssen oder möchten, können Sie dies auch tun.

 #!/bin/bash

shopt -s dotglob nullglob

Funktion rekursiv {

  lokales aktuelles_dir dir_or_file

  für aktuelles_dir in $1; tun

    echo "Verzeichnisbefehl für:" $aktuelles_dir

    für dir_or_file in "$aktuelles_dir"/*; tun

      if [[ -d $dir_or_file ]]; dann
        rekursives "$dir_or_file"
      anders
        wc $dir_or_file
      fi
    erledigt
  erledigt
}

rekursiv "$1"

Kopieren Sie den Text in einen Editor und speichern Sie ihn als „recurse.sh“, dann verwenden Sie den Befehl chmod , um ihn ausführbar zu machen.

 chmod +x recurse.sh 

Das recurse.sh-Skript ausführbar machen

Das Skript setzt zwei Shell-Optionen, dotglob und nullglob .

Die dotglob Einstellung bedeutet Datei- und Verzeichnisnamen, die mit einem Punkt beginnen „ . “ wird zurückgegeben, wenn Suchbegriffe mit Platzhaltern erweitert werden. Dies bedeutet effektiv, dass wir versteckte Dateien und Verzeichnisse in unsere Suchergebnisse aufnehmen.

Die nullglob Einstellung bedeutet, dass Suchmuster, die keine Ergebnisse finden, als leere oder Nullzeichenfolge behandelt werden. Sie verwenden nicht standardmäßig den Suchbegriff selbst. Mit anderen Worten, wenn wir mit dem Sternchen-Platzhalter „ * “ nach allem in einem Verzeichnis suchen, aber keine Ergebnisse erhalten, erhalten wir einen Null-String anstelle eines Strings, der ein Sternchen enthält. Dadurch wird verhindert, dass das Skript versehentlich versucht, ein Verzeichnis mit dem Namen „*“ zu öffnen oder „*“ als Dateinamen zu behandeln.

Als nächstes definiert es eine Funktion namens recursive . Hier passieren die interessanten Dinge.

Es werden zwei Variablen namens current_dir und dir_or_file . Dies sind lokale Variablen und können nur innerhalb der Funktion referenziert werden.

Innerhalb der Funktion wird auch eine Variable namens $1 verwendet. Dies ist der erste (und einzige) Parameter, der an die Funktion übergeben wird, wenn sie aufgerufen wird.

Grundierung: Bash Loops: for, while und until
VERWANDTER Primer: Bash Loops: for, while und until

Das Skript verwendet zwei for -Schleifen, von denen eine in der anderen verschachtelt ist. Die erste (äußere) for -Schleife wird für zwei Dinge verwendet.

Eine besteht darin, den gewünschten Befehl in jedem Verzeichnis auszuführen. Alles, was wir hier tun, ist, den Namen des Verzeichnisses an das Terminalfenster zurückzugeben. Sie könnten natürlich jeden Befehl oder jede Befehlsfolge verwenden oder eine andere Skriptfunktion aufrufen.

Als Zweites überprüft die äußere for-Schleife alle Dateisystemobjekte, die sie finden kann – entweder Dateien oder Verzeichnisse. Dies ist der Zweck der inneren for -Schleife. Jeder Datei- oder Verzeichnisname wird wiederum an die dir_or_file Variable übergeben.

Die Variable dir_or_file wird dann in einer if-Anweisung getestet, um zu sehen, ob es sich um ein Verzeichnis handelt.

  • Ist dies der Fall, ruft sich die Funktion selbst auf und übergibt den Namen des Verzeichnisses als Parameter.
  • Wenn die Variable dir_or_file kein Verzeichnis ist, muss es sich um eine Datei handeln. Alle Befehle, die Sie auf die Datei angewendet haben möchten, können von der else -Klausel der if -Anweisung aufgerufen werden. Sie könnten auch eine andere Funktion innerhalb desselben Skripts aufrufen.

Die letzte Zeile im Skript ruft die recursive Funktion auf und übergibt den ersten Befehlszeilenparameter $1 als Startverzeichnis für die Suche. Dies ist der Startschuss für den gesamten Prozess.

Lassen Sie uns das Skript ausführen.

 ./recurse.sh funktionieren 

Verarbeitung der Verzeichnisse vom flachsten zum tiefsten

Die Verzeichnisse werden durchlaufen, und der Punkt im Skript, an dem ein Befehl in jedem Verzeichnis ausgeführt werden würde, wird durch die Zeilen „Verzeichnisbefehl für:“ angezeigt. Auf gefundenen Dateien wird der Befehl wc ausgeführt, um Zeilen, Wörter und Zeichen zu zählen.

Das erste verarbeitete Verzeichnis ist „work“, gefolgt von jedem verschachtelten Verzeichniszweig des Baums.

Ein interessanter Punkt ist, dass Sie die Reihenfolge ändern können, in der die Verzeichnisse verarbeitet werden, indem Sie die verzeichnisspezifischen Befehle von oberhalb der inneren for-Schleife zu unterhalb verschieben.

Lassen Sie uns die Zeile „Directory command for:“ hinter das done der inneren for -Schleife verschieben.

 #!/bin/bash

shopt -s dotglob nullglob

Funktion rekursiv {

  lokales aktuelles_dir dir_or_file

  für aktuelles_dir in $1; tun

    für dir_or_file in "$aktuelles_dir"/*; tun

      if [[ -d $dir_or_file ]]; dann
        rekursives "$dir_or_file"
      anders
        wc $dir_or_file
      fi

    erledigt

    echo "Verzeichnisbefehl für:" $aktuelles_dir

  erledigt
}

rekursiv "$1"

Jetzt führen wir das Skript noch einmal aus.

 ./recurse.sh funktionieren 

Verarbeitung der Verzeichnisse vom tiefsten zum flachsten

Dieses Mal werden die Befehle zuerst von den tiefsten Ebenen auf die Verzeichnisse angewendet und arbeiten sich die Zweige des Baums hinauf. Das als Parameter an das Skript übergebene Verzeichnis wird zuletzt verarbeitet.

Wenn es wichtig ist, zuerst tiefere Verzeichnisse verarbeiten zu lassen, können Sie dies wie folgt tun.

Rekursion ist seltsam

Es ist, als würde man sich selbst auf seinem eigenen Telefon anrufen und eine Nachricht für sich selbst hinterlassen, um sich selbst mitzuteilen, wann man sich das nächste Mal trifft – immer wieder.

Es kann einige Anstrengungen erfordern, bevor Sie die Vorteile erkennen, aber wenn Sie dies tun, werden Sie feststellen, dass dies eine programmatisch elegante Möglichkeit ist, schwierige Probleme anzugehen.

VERWANDT: Was ist Rekursion in der Programmierung und wie wird sie verwendet?