Wie arbeite ich mich rekursiv durch einen Verzeichnisbaum und führe einen bestimmten Befehl für jede Datei aus und gebe den Pfad, den Dateinamen, die Erweiterung, die Dateigröße und einen anderen bestimmten Text in einer einzelnen Datei in Bash aus.
14
Antworten:
Obwohl die
find
Lösungen einfach und leistungsstark sind, habe ich beschlossen, eine kompliziertere Lösung zu erstellen, die auf dieser interessanten Funktion basiert , die ich vor einigen Tagen gesehen habe.1. Erstellen Sie eine ausführbare Skriptdatei mit dem Namen
walk
,/usr/local/bin
auf die Sie als Shell-Befehl zugreifen können:nano
: Shift+ Insertzum Einfügen; Ctrl+ Ound Enterzum Speichern; Ctrl+ Xzum Verlassen.2. Der Inhalt des Skripts
walk
ist:3. Erklärung:
Der Hauptmechanismus der
walk()
Funktion wird von Zanna in ihrer Antwort ziemlich gut beschrieben . Also werde ich nur den neuen Teil beschreiben.Innerhalb der
walk()
Funktion habe ich diese Schleife hinzugefügt:Das heißt, für jede
$entry
Datei wird die Funktion ausgeführtfile_specification()
.Die Funktion
file_specification()
besteht aus zwei Teilen. Der erste Teil bezieht sich auf den Dateinamen, den Pfad, die Größe usw. Der zweite Teil gibt die Daten in gut formatierter Form aus. Zum Formatieren der Daten wird der Befehl verwendetprintf
. Und wenn Sie das Skript optimieren möchten, sollten Sie diesen Befehl lesen - zum Beispiel diesen Artikel .Die Funktion
file_specification()
ist ein guter Ort, an dem Sie den spezifischen Befehl eingeben können, der für jede Datei ausgeführt werden soll . Verwenden Sie dieses Format:Oder Sie können die Ausgabe des Befehls als Variable speichern und dann
printf
diese Variable usw .:Oder direkt
printf
die Ausgabe des Befehls:Der aufgerufene Abschnitt zum Aufrufen
Colourise the output
initialisiert einige Variablen, die imprintf
Befehl zum Färben der Ausgabe verwendet werden. Mehr dazu finden Sie hier .Am unteren Rand des Skripts wird eine zusätzliche Bedingung hinzugefügt, die sich mit absoluten und relativen Pfaden befasst.
4. Anwendungsbeispiele:
So führen Sie
walk
das aktuelle Verzeichnis aus:So führen Sie ein
walk
beliebiges untergeordnetes Verzeichnis aus:So führen Sie
walk
ein anderes Verzeichnis aus:So erstellen Sie eine Textdatei basierend auf der
walk
Ausgabe:So erstellen Sie eine Ausgabedatei ohne Farbcodes ( Quelle ):
5. Demonstration der Nutzung:
quelle
Ich bin ein wenig ratlos darüber, warum es noch niemand gepostet hat, aber ich habe tatsächlich
bash
rekursive Fähigkeiten, wenn Sie dieglobstar
Option aktivieren und**
glob verwenden. Als solches können Sie ein (fast) reinesbash
Skript schreiben , das diesen rekursiven Globstar wie folgt verwendet:Beachten Sie, dass wir hier die Parametererweiterung verwenden, um die gewünschten Teile des Dateinamens abzurufen, und uns nicht auf externe Befehle verlassen, außer die Dateigröße mit
du
abzurufen und die Ausgabe mit zu bereinigenawk
.Und während es Ihren Verzeichnisbaum durchläuft, sollte Ihre Ausgabe ungefähr so aussehen:
Standardregeln der Skriptgebrauch gelten: Stellen Sie sicher , ist es ausführbar mit
chmod +x ./myscript.sh
und aus aktuellen Verzeichnis laufen über./myscript.sh
oder es an seinem Platz~/bin
und laufensource ~/.profile
.quelle
"$(file "$i")"
(im obigen Skript als zweiter Teil eines printf) zurückkehren würden?output the path, filename, extension, filesize
, stimmt mit der gestellten Frage überein. :)Sie können verwenden
find
, um die Arbeit zu erledigenDies hilft Ihnen, wenn Sie nur alle Dateien mit der Größe auflisten möchten.
-exec
Damit können Sie einen benutzerdefinierten Befehl oder ein benutzerdefiniertes Skript für jede Datei ausführen,\;
die zum Analysieren von Dateien nacheinander verwendet wird. Diese Option können Sie verwenden,+;
wenn Sie sie verketten möchten (dh Dateinamen).quelle
Mit
find
nur.Oder Sie könnten stattdessen Folgendes verwenden:
quelle
find -printf
). +1Wenn Sie wissen, wie tief der Baum ist, können Sie am einfachsten die Platzhalter verwenden
*
.Schreiben Sie alles, was Sie tun möchten, als Shell-Skript oder als Funktion auf
dann laufen
for i in *; do thing "$i"; done
,for i in */*; do thing "$i"; done
... etcInnerhalb Ihrer Funktion / Ihres Skripts können Sie einige einfache Tests verwenden , um die Dateien herauszusuchen, mit denen Sie arbeiten möchten, und um alles zu tun, was Sie dazu benötigen.
quelle
$i
.for i in */*
funktioniert. Hier, testen Sie es:for i in */*; do printf "|%s|\n" "$i"; done
find
kann dies tun:Schauen Sie sich
man find
andere Dateieigenschaften an.Wenn Sie die Erweiterung wirklich benötigen, können Sie Folgendes hinzufügen:
quelle