diff --git a/beispiele.tex b/beispiele.tex index b1d299d..1213e45 100644 --- a/beispiele.tex +++ b/beispiele.tex @@ -336,3 +336,90 @@ esac Wenn \texttt{case} eine andere Parameterzahl feststellt, wird eine Meldung mit der Aufrufsyntax auf die Standard-Fehlerausgabe geschrieben. \end{flushright} \index{trap=\texttt{trap}|)}\index{Signal|)} + + +\section{Chaoten: Dateien in zufällige Reihenfolge +bringen}\label{chaoten}\index{Zufallszahlen|(} + +Wir wollen uns einen MP3-Player programmieren, der Alle MP3-Dateien aus einem +bestimmten Verzeichnisbaum in zufälliger Reihenfolge abspielt. Damit dieses +Problem für uns eine Herausforderung darstellt\footnote{Denn schließlich hat +mpg123 schon von Hause aus eine Random-Funktion}, wollen wir vor dem Abspielen +der jeweiligen Datei etwas mit dem Dateinamen anstellen. Ob das eine einfache +Ausgabe per \texttt{echo} ist, oder ob der Name per Sprachsynthese oder auf +einem externen Display angezeigt werden soll ist an dieser Stelle egal. + +Das Problem ist, daß wir in der Shell nur über Umwege an Zufallszahlen kommen +können. Auf Systemen, in denen die Datei \texttt{/dev/urandom} existiert, +liefert uns der Kernel aber schon sehr zufällige Zeichenfolgen. Diese Folgen +können alle Zeichen enthalten, daher müssen sie vor der Benutzung für unsere +Zwecke noch etwas 'bereinigt' werden. + +Wie das aussieht, wenn es fertig ist, sieht man im folgenden Skript: + +\footnotesize +\index{!==\texttt{!=}} +\begin{listing}[2]{1} +#!/bin/sh +for i in `find $1 -type f -name "*.[mM][pP]3"`; do +\end{listing} +\normalsize +\begin{flushright} +Hier beginnt eine Schleife, die über alle Ausgaben des \texttt{find}-Kommandos +iteriert. Dabei sucht \texttt{find} nach allen normalen Dateien (\texttt{-type +f}), die die Extension .mp3 tragen (\texttt{-name \dq*.[mM][pP]3\dq} -- wir +ignorieren Groß- / Kleinschreibung). +\end{flushright} +\footnotesize +\index{find=\texttt{find}} +\begin{listingcont} + echo `tr -dc "[:alpha:]" < /dev/urandom | \ + dd count=8 bs=1 2> /dev/null`$i +\end{listingcont} +\normalsize +\begin{flushright} +Hier ist der 'magische Teil'. Mit dem \texttt{echo} wird die Ausgabe einer Pipe +ausgegeben, gefolgt von dem aktuellen Dateinamen. Diese Pipe enthält ein +\texttt{tr}, der alle ungewollten Zeichen (alles, was kein Textzeichen ist) aus +einem Datenstrom entfernt. Die Daten erhält \texttt{tr} durch die +\texttt{<}-Umleitung aus oben genannter Datei. + +Diese Datei liefert 'ohne Ende' Zeichen. Wir wollen aber nur acht Zeichen +haben, die wir unserem Dateinamen voranstellen können. Dazu benutzen wir das +Kommando \texttt{dd} mit den angegebenen Parametern. Damit die Erfolgsmeldung +von \texttt{dd} nicht die Ausgabe verunstaltet, lenken wir sie nach +\texttt{/dev/null} um. +\index{tr=\texttt{tr}}\index{dd=\texttt{dd}} +\end{flushright} +\footnotesize +\index{find=\texttt{find}} +\begin{listingcont} +done | sort | cut -b 9- | while read i; do +\end{listingcont} +\normalsize +\begin{flushright} +Das Ergebnis der obigen Schleife ist also die Liste der Dateinamen, denen +jeweils acht zufällige Zeichen vorangestellt wurden. Die Reihenfolge entspricht +allerdings immer noch der Ausgabe von \texttt{find}, wird also nach jedem +Durchlauf gleich sein. + +Um das zu ändern, pipen wir die Ausgabe der Schleife durch ein \texttt{sort}. +Da die ersten acht Zeichen jeder Zeile zufällig sind, erhalten wir so eine +zufällige Reihenfolge der Zeilen. Jetzt müssen wir nur noch durch ein +\texttt{cut} die zufälligen Zeichen abschneiden, und erhalten so die +ursprüngliche Liste von Dateien in einer zufälligen Reihenfolge. + +Diese lesen wir jetzt zeilenweise mittels \texttt{read} ein. In der +\texttt{while}-Schleife können wir alle erforderlichen Sachen mit dem +Dateinamen anstellen. Hier wird er nur mittels \texttt{echo} ausgegeben. +\index{sort=\texttt{sort}}\index{cut=\texttt{cut}} \index{read=\texttt{read}}\index{while=\texttt{while}} +\end{flushright} +\footnotesize +\index{find=\texttt{find}} +\begin{listingcont} + echo "Jetzt wird $i gespielt" + mpg123 "$i" +done +\end{listingcont} +\normalsize +\index{Zufallszahlen|)}