Programmer's Toolbox (6): Erste rekursive Kommandos

Mit der Fähigkeit zur Argumentexpansion erschließen sich eine ganze Reihe von neuen Einsatzmöglichkeiten für Kommandos. Im folgenden sollen davon die untenstehenden Kommandos realisiert werden.

LS - Anzeigen von Dateiinformationen
CP - Dateien kopieren
MV - Dateien bewegen

Alle Kommandos verbindet dabei die Tatsache, daß sie zunächst ihre Argumente mit Hilfe der Funktionen aus EXPAND bearbeiten. Dabei werden je nach Situation sowohl vertikale als auch horizontale Argumentexpansionen vorgenommen. Nachfolgend wird dann die resultierende Struktur rekursiv durchlaufen. Als Nebeneffekt des Durchlaufs führt das Kommando seine eigentliche Wirkung durch. Abschließend wird die Struktur - ebenfalls wieder mit den Funktionen aus EXPAND - freigegeben.

Bei der Notation der Kommandos wird dabei der gleiche Formalismus, wie bereits bei den einfachen Kommandos des vorletzten Serienteils verwendet.

Das Kommando LS

NAME

LS - Anzeigen von Dateiinformationen

ANWENDUNG

LS [ -ADLRT ] Dateiname...

BESCHREIBUNG

Für jeden Dateinamen, der für ein Verzeichnis steht, listet LS den Inhalt des Verzeichnisses; für jeden Dateinamen, der eine normale Datei ist, wiederholt LS den Namen und gibt (wenn gewünscht) weitere Informationen aus. Standardmäßig wird die Ausgabe alphabetisch sortiert. Wenn kein Argument übergeben wird, erfolgt die Ausgabe des Arbeitsverzeichnisses. Wenn Argumente übergeben werden, so werden sie zunächst alphabetisch sortiert bevor weiterverfahren wird.

Werden Einträge in ihrer Langversion ("-L" Option) ausgegeben, dann wird folgende Konvention für die Ausgabe der Dateiattribute benutzt:

Das erste Zeichen besitzt zwei Möglichkeiten mit folgender Bedeutung:

d Der Eintrag weißt auf ein Unterverzeichnis

Das zweite Zeichen kennzeichnet den Lesezugriff:

r Es besteht Lesezugriff

Das dritte und letzte Zeichen kennzeichnet den Schreibzugriff:

w Es besteht Schreibzugriff

BEISPIEL

Ein Beispiel für die Ausgabe von Dateiattributen mit Hilfe von "LS -L" könnte folgendermassen aussehen:

-rw beispiel.txt 01-11-89 12:00:00 1234567

In erster Position sind die Dateiattribute dargestellt. Das Beispiel zeigt eine Datei, auf die schreibend und lesend zugegriffen werden darf. An zweiter Stelle befindet sich der Dateiname, gefolgt von dem Datum der letzten Bearbeitung und der Dateigröße.

OPTIONEN

-A Liste alle Einträge; in Abwesenheit von "-A" werden Einträge, die mit "." beginnen nicht ausgegeben.
-D Wenn Argumente Verzeichnisse sind, wird nur ihr Name ausgegeben.
-L Liste die Einträge in ihrer Langversion. Die Langversion enthält die Dateiattribute, die Dateigröße und das Datum der letzten Modifikation (siehe oben)
-R Rekursive Ausgabe der Verzeichnisse.
-T Sortierung nach dem Zeitpunkt der letzten Modifikation

ANMERKUNG

-D und -R setzen sich wechselweitig zurück. Folgende Aufrufe von LS entsprechen sich daher:

LS -R -D entspricht LS -D
LS -D -R entspricht LS -R

PROGRAMMIERUNG

Das Kommando LS ist in Listing 1.12 programmiert. Innerhalb des Listings wenden wir uns zunächst der gleichnamigen Funktion ls (Zeilen 179-238) zu. Im Variablendeklarationsteil erkennt man zunächst die Initialzustände für die Optionen des Kommandos. Initial wird davon ausgegangen, daß die unsichtbaren Verzeichnisse nicht mit angegeben werden (Zeile 187), daß Verzeichnisse nicht komplett ausgegeben werden (Zeile 188), daß die Ausgabe nicht rekursiv erfolgt (Zeile 189), daß die Dateien nicht in ihrer Langversion ausgegeben werden (Zeile 190). Als Sortierung wird "Sortierung nach dem Dateinamen" vorgegeben (Zeile 191). Der erste Bereich des Anweisungsteils von ls dient nun zur Interpretation von möglichen Optionen. In einer for-Schleife wird dabei zunächst auf die fünf möglichen Optionen des Kommandos LS geprüft. Das wechselseitige Zurücksetzen von "-D" und "-R" ist dabei in den Zeilen 201-202 und 206-207 berücksichtigt. Beim Auftreten des ersten Argumentes wird die dlist erzeugt (Zeilen 218-223) und eine Marke (argument) wird gesetzt, damit alle nachfolgenden Parameter als Argumente erkannt werden. Mögliche weitere Argumente werden danach, unter Anwendung von expand_dlist, in die dlist aufgenommen (Zeile 225-226).

Nach dem Verlassen der for-Schleife muß nun noch geprüft werden, ob überhaupt Argumente gefunden wurden. Ist dies nicht der Fall, dann wird die dlist mit dem aktuellen Verzeichnis aufgebaut (Zeilen 229-234). Danach wird die erhaltene Struktur mit der Funktion list_dlist ausgegeben und dann mit drop_dlist freigegeben.

Wenn wir uns nun der Ausgabefunktion list_dlist (Zeilen 155-163) und den eingeschachtelten Folgeaufrufen von list_dir (Zeilen 145-153) und list_flist (Zeilen 66-143) zuwenden, dann läßt sich hier zunächst die bereits zweimal angetroffene hierarchische Schachtelung der Funktionen erkennen. Lediglich auf der untersten Ebene wird kein rekursiver Aufruf von list_flist durchgeführt, stattdessen findet man hier Schleifen zum Listendurchlauf. Eigentlich ist das weniger elegant, aber wie Sie gleich sehen werden leider notwendig. list_flist erhält nämlich gerade die Aufgabe die Dateiinformationen der übergeben FILE_DESC_LIST auszugeben. Es ist dabei zwischen einer Ausgabe als Langversion (Zeilen 86-101) und einer Normalausgabe (Zeilen 104-141) zu unterscheiden. Die Ausgabe der Langversion ist bis auf die Ausgabeformatierung recht einfach - ein normaler Listendurchlauf. Es wird lediglich eine Hilfsfunktion (list_date, 44-56) verwendet, um den Modifikationszeitpunkt der jeweils betrachteten Datei formatiert auszugeben. Hier findet sich also nichts, was eine rekursive Formulierung verhindern würde. Stattdessen befindet sich der Rekursionskiller in der Ausgabe der Kurzversion. Da die Ausgabe der Dateiinformationen hier nicht untereinander geschieht, sondern in Spalten nebeneinander, kann die FILE_DESC_LIST nicht linear (Element für Element) durchlaufen werden. Zunächst ist hier nämlich die Gesamtanzahl der Dateien zu ermitteln (Zeilen 104-109). Es folgt die Ermittlung der Teillisten, die in den einzelnen Spalten ausgegeben werden sollen (Zeilen 110-124). Erst dann kann die Ausgabe durchgeführt werden (Zeilen 125-130). Zur Anwendung kommt eine weitere Hilfsfunktion (outname, Zeilen 58-64).

Das Kommando CP

NAME

CP - Dateien kopieren

ANWENDUNG

CP [ -I ] Dateiname1 Dateiname2
CP [ -I ] Dateiname... Verzeichnis

BESCHREIBUNG

Die erste Variante von CP kopiert den Inhalt von Dateiname1 nach Dateiname2.

In einer weiteren Variante kopiert CP die Inhalte von mehreren Dateinamen in ein angegebenes Verzeichnis. Dateiname darf dabei auch ein Unterverzeichnis sein. In diesem Fall kopiert CP den kompletten Inhalt des Unterverzeichnis (mit sämtlichen darin enthaltenen Verzeichnissen) in das angegebene Verzeichnis. Existiert Verzeichnis dabei nicht, dann wird es von CP angelegt. Ferner legt CP noch sämtliche für die Anfertigung der Kopie notwendigen Unterverzeichnisse innerhalb von Verzeichnis an.

CP weigert sich einen Dateinamen auf sich selbst zu kopieren.

OPTIONEN

-I Interaktivmodus. Immer wenn beim Kopieren eine bereits existierende Datei überschrieben wird, wird ein "y" als Bestätigung verlangt. Jede andere Antwort hindert CP am Überschreiben der Datei.

BEISPIEL

Das Kopieren einer Datei:

 CP  BEISPIEL.C  BEISPIEL.BAK

Das Kopieren mehrerer Dateien in ein gemeinsames Verzeichnis:

 CP  BEISPIEL.C  BEISPIEL.BAK A:\

PROGRAMMIERUNG

Das Kommando CP ist in Listing 1.13 programmiert. Die gleichnamige Hauptfunktion cp (Zeilen 118-186) hat nicht übermässig viele Optionen zu berücksichtigen. Lediglich "-I", die Option für Interaktion beim Kopieren, ist erlaubt und wird gegebenenfalls in den Zeilen 135-138 erkannt und gesetzt. Danach folgt ein Programmteil zur Durchführung der Argumentexpansion für die restlichen Parameter (Zeilen 142-153). Es folgen zwei if-Anweisungen, die sicherstellen, daß CP nur mit einer zulässigen Argumentkombination aufgerufen wird (Zeilen 154-161). In der inneren if-Anweisung wird letztlich entschieden, ob CP gemäß der ersten Parametrisierung aufgerufen worden ist, oder ob die allgemeinere, zweite Parametrisierung vorliegt. Im ersten Fall wird CP durch das Kopieren einer einzigen Datei beendet (Zeile 160-161). Der zweite Fall ist umfangreicher, da nun entsprechend der Dateibeschreibungen in der DIR_DESC_LIST kopiert werden muß. Möglicherweise erfolgt das Kopieren dabei in ein Verzeichnis, daß noch gar nicht existiert. In diesem Fall ist es zuvor zu erzeugen (Zeilen 163-169). Danach wird der Kopiervorgang eingeleitet. Die bereits vertraut wirkenden drei Funktionen cp_flist, cp_dir und cp_dlist führen einen rekursiven Durchlauf durch die DIR_DESC_LIST durch. Zusätzlich zu den bisher betrachteten, rekursiven Durchläufen in anderen Kommandos, ist es bei CP noch erforderlich, Quell- (srcpath) und Zielpfad (destpath) als Parameter zu übergeben und bei der rekursiven Einschachtelung zu expandieren. Damit erhält man die absoluten Pfade für die Dateikopiervorgänge in cp_flist. Beobachten läßt sich das etwa in den Zeilen 50-53. Außerdem müssen auch in cp_flist vor der Einschachtelung Verzeichnisse erzeugt werden (Zeilen 55-60), da es in TOS nicht möglich ist, Dateien in nicht-existente Verzeichnisse zu kopieren (und diese dadurch gegebenenfalls zu erzeugen).

Das Kommando MV

NAME

MV - Dateien bewegen

ANWENDUNG

MV [ -I ] Dateiname1 Dateiname2
MV [ -I ] Dateiname... Verzeichnis

BESCHREIBUNG

MV bewegt Dateien und Verzeichnisse im Dateisystem. Die zwei Varianten von MV sind unter ANWENDUNG aufgeführt und sollen kurz erläutert werden:

Die erste Variante von MV bewegt Dateiname1 unter Umbenennung nach Dateiname2. Wenn Dateiname2 bereits existiert hat, wird er dabei gelöscht. Wenn Dateiname2 jedoch gegen Überschreiben geschützt ist (siehe CHMOD), dann gibt MV eine entsprechende Meldung aus und bricht den Bewegevorgang ab.

In einer weiteren Variante bewegt MV die Inhalte von mehreren Dateinamen in ein angegebenes Verzeichnis. Dateiname darf dabei auch ein Unterverzeichnis sein. In diesem Fall bewegt MV den kompletten Inhalt des Unterverzeichnisses (mit sämtlichen darin enthaltenen Verzeichnissen) in das angegebene Verzeichnis. Existiert Verzeichnis dabei nicht, dann wird es von MV angelegt. Ferner legt MV noch sämtliche für die Kopie notwendigen Unterverzeichnisse innerhalb von Verzeichnis an.

MV weigert sich Dateien/Verzeichnisse auf sich selbst zu bewegen.

OPTIONEN

-I Interaktivmodus. MV zeigt immer dann den Namen einer Datei oder eines Verzeichnisses, wenn eine Bewegeoperation eine bereits existierende Datei überschreibt. Unter Eingabe eines "y" überschreibt MV diese Datei, andernfalls wird die Datei nicht bewegt.

PROGRAMMIERUNG

Das Kommando MV ist in Listing 1.14 programmiert. Die Implementierung ähnelt weitgehend der Implementierung von CP. Bis auf Umbenennungen weicht Listing 1.14 nur an zwei Stellen von Listing 1.13 ab: In den Zeilen 65-67 und in den Zeilen 89-91 befinden sich zwei Einschübe gegenüber den entsprechenden Programmstellen in CP. An diesen Programmstellen wird im rekursiven Rücklauf der Funktion mv_flist ein Löschen der nun leeren Quellverzeichnisse vorgenommen. Die betroffenen Dateien sind zuvor bereits durch die Aufrufe von amv gelöscht worden.

Vorausschau

Mit den heute betrachteten drei Kommandos ist die Thematik der rekursiven Kommandos noch nicht erschöpft. Beim nächsten Mal werden daher weitere Kommandos eingeführt, die Argumentexpansion benutzen. Es handelt sich dabei um:

RM - Löschen von Dateien
RMDIR - Löschen von Verzeichnissen
MKDIR - Erzeugen von Verzeichnissen
CHMOD - Ändern des Dateizugriffsmodus
TOUCH - Aktualisierung der Modifikationszeit von Dateien

Listings zur Programmer's Toolbox (6)


Dirk Brockhaus
Aus: ST-Computer 12 / 1990, Seite 116

Links

Copyright-Bestimmungen: siehe Über diese Seite