![]() |
![]() |
Im vorletzten Kapitel wurde in die grundlegenden Funktionen von DOS eingeführt: Sich im Verzeichnisbaum bewegen, Dateien erzeugen, kopieren, löschen. Nichts, was man nicht mit einem Dateimanager wie dem Windows-Explorer auch könnte.
In diesem Kapitel kommen nun DOS-Fähigkeiten zur Sprache, die schon näher ans Programmieren heranführen. Und die in Verbindung mit einer Programmiersprache ganz erstaunliche Dinge ermöglichen. Das Prinzip dieser "erstaunlichen Dinge" sei schon vorweggenommen: Wir können später von unseren selbst geschriebenen Programmen aus DOS-Kommandos absetzen. Und damit all die DOS-Funktionen in unseren Programmen nutzen, die wir schon kennengelernt haben und noch kennenlernen werden. Und das ist der wesentliche Unterschied zu ihrem Dateimanager: Den können Sie aus einem eigenen Programm heraus nicht benutzen und automatisieren (jedenfalls nicht so ohne weiteres.)
Ein Dateiname bestand unter DOS immer aus bis zu acht Buchstaben Name und 3 Buchstaben Suffix. Also z.B. "command.com" oder "meintext.txt". Diese Regelung wurde durch DOS von seinem Vorläufer CP/M übernommen. Die 8-Buchstaben- Grenze ist längst gestrichen. Heute kann man Dateinamen mit über 200 Buchstaben generieren - wem das Spass macht. Aber die Suffixe werden weiterhin beibehalten. Sie sind sogar elementar geworden. Denn anhand ihnen wird identifiziert, um was für einen Dateityp es sich handelt und mit welchem Programm man ihn bearbeiten kann. Ein paar bekannte Suffixe und die in der Regel zuständigen Programme sind:
Suffix | Zuständiges Programm |
doc | Microsoft Word |
xls | Microsoft Excel |
Acrobat Reader-Datei | |
html | WWW-Browser |
txt | Editor |
gif | Bildbetrachter |
jpg | Bildbetrachter |
mp3 | MP3-Player (Musikprogramm) |
mpeg | Video-Player |
avi | Video-Player |
bas | Basic-Interpreter |
u.v.m.
Suffixe machen es also theoretisch möglich, alle Dateien eines Typs auf einmal zu behandeln oder auszuwählen. Man muss nur alle Dateien mit einem bestimmten Suffix ansprechen. Geht das aber auch praktisch? Klar doch.
DOS beherrscht s.g. "Wildcards". Das sind Symbole im Dateinamen. Entweder ein ? oder ein *. Wesentlich wichtiger als das ? ist *. Er steht für einen beliebigen String. Das heisst, es werden durch diesen Namen alle Dateien bezeichnet, deren Name mit den angegeben Buchstaben übereinstimmt, aber an der Stelle des * irgendetwas stehen haben.
Ein Beispiel sagt hier mehr als tausend Worte: "n*t" steht für alle Namen, die mit n beginnen und mit t enden, also "nagt", "näht", "numeriert", "ndjskdjht", "n182kt".
"*.txt" steht für alle Namen, die mit ".txt" enden, also "a.txt", "meintext.txt", "hallo.txt" usw.
"hallo*.*" steht für alle Namen, die mit "hallo" beginnen, also "hallo1.txt", "hallodies.bas", "hallohallo.doc".
Das ? hingegen steht für genau einen beliebigen Buchstaben. "hallo.???" z.B. meint "hallo.txt", "hallo.doc", aber nicht "hallo.html".
Vielen DOS-Befehlen kann man oder muss man Dateinamen beifügen. Durch Verwendung von Wildcards kann man nun ganz flexibel ganze Dateigruppen mit einem Schlag behandeln. Ein paar Beispiele
dir *.txt | Zeige alle Textdateien |
dir /s *.txt | Zeige alle Textdateien in diesem Verzeichnis und allen Unterverzeichnissen. |
type *.htm | Zeige den Inhalt aller HTML-Dateien auf dem Bildschirm an. |
xcopy /s *.bas A: | Kopiere alle Basic-Programme aus dem aktuellen Verzeichnis und allen Unterverzeichnissen (Option /s) auf eine Diskette |
xcopy /s *.* A: | Kopiere ALLE Dateien aus dem aktuellen Verzeichnis und allen Unterverzeichnissen (Option /s) auf eine Diskette |
xcopy /s /d:01-01-2003 *.* A: | Kopiere alle Dateien, die seit dem 01.01.2003 verändert oder erstellt wurden, aus dem aktuellen Verzeichnis und allen Unterverzeichnissen (Option /s) auf eine Diskette |
ren a*.jpeg a*.jpg | Benenne alle Bilder, die mit a anfangen und die Endung .jpeg tragen, in .jpg um. |
Wildcards sind zunächst keine Eigenschaft von DOS, sondern lediglich eine Konvention unter DOS. Die Interpretation der Wildcards muss das entsprechende Programm selbst übernehmen (ganz im Gegensatz zu Unix, das Wildcards für das entsprechende Programm in explizite Dateinamen übersetzt).
Das heisst: Ausser dir, copy, xcopy und hier und da ein paar Programmen können wir keine Wildcards verwenden. Denken wir. Es gibt jedoch einen Befehl, der das ermöglicht: Eine FOR-Schleife.
Syntax: for %1 in (
Noch eine kleine lustige Anekdote zu Wildcards, die sich während meiner Diplomarbeitszeit ereignet hat. Das Betriebssystem, auf dem alle arbeiteten, war UNIX. Da aber viele Dinge bei DOS von UNIX abgeschaut sind, (auch die Pipes im folgenden Abschnitt), verwundert es nicht, dass die Wildcards bei UNIX fast genau gleich funktionieren. Nur gibt es dort noch mehr und man kann noch viel kompliziertere Dinge mit ihnen tun. Und: Suffixe gibt es unter Unix nicht zwingend. Wenn man unter DOS alle Dateien ansprechen möchte, muss man "*.*" formulieren, unter UNIX nur "*". Der del-Befehl heisst unter Unix übrigens "rm".
Eines Tages kam ein Mitarbeiter sehr zerknirscht zum System-Administrator und fragte ihn: "Du, wann ist denn das letzte Backup gemacht worden?". Alle horchten auf. Was war passiert? Der Mitarbeiter war für eine Stunde von seiner Workstation weggegangen. Als er wiederkam, befand sich eine Datei namens "*" in seinem Verzeichnis. Das störte ihn. Also löschte er sie: "rm *". Den Rest können Sie sich denken...
Für DOS ist alles eine Datei. Nicht nur die Datei auf dem Datenträger, sondern auch der Bildschirm und die Tastatur. Schreibt ein Programm auf den Bildschirm, so schreibt es in Wirklichkeit in eine Datei, die laufend auf dem Bildschirm angezeigt wird. Diese nennt man die "Standardausgabe". Entsprechend gibt es auch die "Standardeingabe", die Datei, aus der ein Programm die Tastatureingaben liest.
Der Vorteil dieses Prinzips ist, dass man diese Datei ändern kann. Die Standardeingabe muss nicht zwingend mit der Tastatur verbunden sein. Sondern man kann DOS auch anweisen, ein Programm so auszführen, dass die Standardeingabe eine Datei ist. Das Programm nimmt also an, es bekäme seine Eingaben über die Tastatur, in Wirklichkeit kommen sie aber aus einer Textdatei. Das ist sehr praktisch. Fragt ein Programm z.B. über die Tastatur eine Menge Informationen ab, so kann ich diese auch einfach mit einem Editor in eine Datei schreiben und dem Programm diese Datei "vor die Nase setzen".
Und wie geht das? <Befehl> > <file> leitet die Standardausgabe auf <file> um. Schreibt <Befehl> also auf den Bildschirm (und das tun die meisten Befehle), dann geht die Ausgabe jetzt in die Datei <file>. "dir > a.lst" schreibt z.B. die Verzeichnisinformationen in die Datei a.lst. Sehr viel mehr sinnvolle Anwendungen der Dateiumleitung mit den elementaren DOS-Befehlen finde ich gerade nicht, aber diese ist sehr praktisch. Praktisch sind auch Dateiumleitungen mit selbst geschriebenen Programmen - dazu später mehr.
Das Zeichen für die Umleitung der Dateieingabe ist übrigens <
Wir können das for-Schleifen-Beispiel von oben noch durch eine Umleitung ergänzen, da es praktisch wäre, das Ergebnis der Stringssuche in einer Datei zu haben, wo man hin- und herblättern kann. Das geht ganz einfach: for %1 in (*.txt) do grep "Hallo!" a.txt > a.lst. Anschliessend sind die Fundstellen in a.txt aufgelistet.
Dann gibt es noch die Pipes. Man kann eine ganze Folge von DOS-Befehlen miteinander verketten, indem man die Standardausgabe des ersten Befehls zur Standardeingabe des nächsten macht. Das nennt man "Piping". ("Pipes" sind auf deutsch "Röhren", hier ist insbesondere die Rohrpost gemeint.) Das einzige Piping, das ich bisher verwendet habe, ist "type <file> | more". "more" ist ein Programm, das von der Standardeingabe liest und das Ergebnis gleich wieder auf dem Bildschirm anzeigt - wenn der Bildschirm voll ist, wartet es auf einen Tastendruck. Auf diese Art und Weise kann man den type-Befehl dazu einsetzen, eine lange Textdatei bildschirmseitenweise auszugeben. Soweit ich weiss, funktioniert das Piping auch nicht so gut unter Windows, da es eigentlich den synchronen Betrieb zweier Programme und das Lesen einer gemeinsamen Datei erfordert, was zumindest unter DOS eigentlich nicht ging.
Nehmen wir an, wir wollen jeden Tag ein Backup unserer Programmierarbeit von Festplatte auf Diskette machen. Wir arbeiten mit fünf Dateien, die myprog?.bas, descr1?.txt, dat1?.dat, mytab?.dat und toolut?.bas heissen sollen. Das ? steht jeweils für eine Ziffer, die die Version angibt. Es soll jeweils nur die neueste Version gesichert werden. Noch dazu sollen die verschiedenen Dateien in verschiedene Verzeichnisse auf der Diskette: Daten sollen nach A:\data und Programme nach A:\prog. Was tun? Jedesmal fünf copy-Befehle auf DOS-Ebene eingeben? Oder fünfmal Dateien im Explorer packen und in das jeweilige Verzeichnis ziehen? Das muss nicht sein!
Die Lösung ist auch ganz einfach: Wir schreiben die fünf Copy-Befehle in eine Textdatei und speichern sie ab. Dann haben wir ein "DOS-Programm". Und das geht tatsächlich. Nennen wir die Datei nämlich mit der Endung .bat, können wir sie wie einen eigenen DOS-Befehl verwenden. Man nennt das einen Skript.
Wir schreiben also mit dem Editor in eine neue Datei
copy C:\prog\myprog7.bas A:\prog copy C:\prog\ toolut7.bas A:\prog copy C:\prog\dat17.dat A:\data copy C:\prog\descr17.txt A:\data copy C:\prog\mytab1.dat A:\data
...und speichern sie als "backup.bat" ab. Anschliessend müssen wir nur noch backup als DOS-Befehl eingeben und die Copy-Befehle werden hintereinander ausgeführt.
...ist leider ziemlich primitiv und mit BASIC nicht zu vergleichen. Daher gibt es inzwischen eine ganze Reihe von (meist kostenlosen) Skriptinterpretern - bis hin zum mächtigen Perl - die mehr können. Für den Anfang wird uns jedoch die Standard-DOS-Skriptsprache genügen. Vor allem, wenn wir sie in Verbindung mit BASIC und anderen Programmiersprachen einsetzen können.
Im folgenden also die Sprachelemente
echo Das ist ein Skript echo Dieser Teil wird ausgeführt goto ende echo Dieser Teil wird nie ausgeführt :ende echo Hier ist das Ende und das wird echo ausgeführt
IF exist %1 GOTO docopy echo Datei existiert nicht! GOTO ende :docopy copy %1 A: :ende
copy %1.bas A: if %2==1 copy %1.dat A:Der Skript heisse backup.bat. Hier kann ich nun auf der Kommandozeile angeben: "backup myprog 0". Dann wird nur myprog.bas nach A. kopiert. Oder ich gebe "backup myprog 1" an. Dann wird auch myprog.dat nach A: kopiert.
test IF errorlevel 1 GOTO docopy GOTO ende :dopcopy copy %1 A: :endeZuerst wird das Programm "test" ausgeführt. Dieses gibt einen Code zurück. Ist dieser Code >=1, dann wird kopiert. Ansonsten wird der docopy-Teil übersprungen.