Viele Aenderungen, Tabellen durch Syntax-Boxen ausgetauscht, neues Kapitel: date

This commit is contained in:
rschaten 2005-01-28 10:07:07 +00:00
parent 68d30297e6
commit 82d1e3e470
27 changed files with 456 additions and 436 deletions

View File

@ -37,7 +37,9 @@ eine entsprechende Meldung ausgegeben.
\subsection{Schleife, bis ein Kommando erfolglos war} \subsection{Schleife, bis ein Kommando erfolglos war}
Analog zum vorhergehenden Beispiel kann man auch ein Skript schreiben, das meldet, sobald sich ein Benutzer abgemeldet hat. Dazu ersetzen wir nur die \texttt{until}- Schleife durch eine entsprechende \texttt{while}-Schleife: Analog zum vorhergehenden Beispiel kann man auch ein Skript schreiben, das
meldet, sobald sich ein Benutzer abgemeldet hat. Dazu ersetzen wir nur die
\texttt{until}- Schleife durch eine entsprechende \texttt{while}-Schleife:
\index{\^=\texttt{\^}}\index{Anführungszeichen}\index{grep=\texttt{grep}}\index{Pipe}\index{sleep=\texttt{sleep}}\index{who=\texttt{who}} \index{\^=\texttt{\^}}\index{Anführungszeichen}\index{grep=\texttt{grep}}\index{Pipe}\index{sleep=\texttt{sleep}}\index{who=\texttt{who}}
\begin{lstlisting} \begin{lstlisting}
@ -48,7 +50,67 @@ done
echo "Die Katze ist aus dem Haus, Zeit, daß die Mäuse tanzen!" echo "Die Katze ist aus dem Haus, Zeit, daß die Mäuse tanzen!"
\end{lstlisting} \end{lstlisting}
Die Schleife wird nämlich dann so lange ausgeführt, bis \texttt{grep}\index{grep=\texttt{grep}} einen Fehler (bzw. eine erfolglose Suche) zurückmeldet. Die Schleife wird nämlich dann so lange ausgeführt, bis
\texttt{grep}\index{grep=\texttt{grep}} einen Fehler (bzw. eine erfolglose
Suche) zurückmeldet.
\section{Subshell-Schleifen vermeiden}\label{subshellschleifen}
Wir wollen ein Skript schreiben, das die \texttt{/etc/passwd} liest und dabei
zählt, wie viele Benutzer eine UID kleiner als 100 haben.
Folgendes Skript funktioniert nicht:
\begin{lstlisting}
#!/bin/sh
count=0
cat /etc/passwd | while read i; do
uid=`echo $i | cut -f 3 -d:`
if [ $uid -lt 100 ]; then
count=`expr $count + 1`
echo $count
fi
done
echo Es sind $count Benutzer mit einer ID kleiner 100 eingetragen
\end{lstlisting}
Was ist passiert?
Dieses Skript besteht im Wesentlichen aus einer Pipe. Wir haben ein
\texttt{cat}-Kom\-man\-do, das den Inhalt der \texttt{/etc/passwd} durch eben
diese Pipe an eine Schleife übergibt. Das \texttt{read}-Kommando in der
Schleife liest die einzelnen Zeilen aus, dann folgt ein Bißchen Auswertung.
Es ist zu beobachten, daß bei der Ausgabe in Zeile 7 die Variable
\texttt{\$count} korrekte Werte enthält. Um so unverständlicher ist es, daß sie
nach der Vollendung der Schleife wieder den Wert 0 enthält.
Das liegt daran, daß diese Schleife als Teil einer Pipe in einer Subshell
ausgeführt wird. Die Variable \texttt{\$count} steht damit in der Schleife
praktisch nur lokal zur Verfügung, sie wird nicht an das umgebende Skript
`hochgereicht'.
Neben der Methode in \ref{daten_hochreichen} bietet sich hier eine viel
einfachere Lösung an:
\begin{lstlisting}
#!/bin/sh
count=0
while read i; do
uid=`echo $i | cut -f 3 -d:`
if [ $uid -lt 100 ]; then
count=`expr $count + 1`
echo $count
fi
done < /etc/passwd
echo Es sind $count Benutzer mit einer ID kleiner 100 eingetragen
\end{lstlisting}
Hier befindet sich die Schleife nicht in einer Pipe, daher wird sie auch nicht
in einer Subshell ausgeführt. Man kann auf das \texttt{cat}-Kommando verzichten
und den Inhalt der Datei durch die Umlenkung in Zeile 9 direkt auf die
Standardeingabe der Schleife (und somit auf das \texttt{read}-Kommando) legen.
\section{Ein typisches Init-Skript}\label{init-skript}\index{Init-Skript} \section{Ein typisches Init-Skript}\label{init-skript}\index{Init-Skript}
@ -248,7 +310,7 @@ echo "aflag=$aflag / Name = $name / Die Dateien sind $*"
\section{Fallensteller: Auf Traps reagieren}\label{traps}\index{trap=\texttt{trap}|(}\index{Signal|(} \section{Fallensteller: Auf Traps reagieren}\label{traps}\index{trap=\texttt{trap}|(}\index{Signal|(}
Ein laufendes Shell-Skript kann durch Druck auf die Interrupt-Taste Ein laufendes Shell-Skript kann durch Druck auf die Interrupt-Taste
(normalerweise \Ovalbox{CTRL}-\Ovalbox{C}) unterbrochen werden. Durch Druck auf (normalerweise \Ovalbox{CTRL}+\Ovalbox{C}) unterbrochen werden. Durch Druck auf
diese Taste wird ein Signal an den entsprechenden Prozeß gesandt, das ihn diese Taste wird ein Signal an den entsprechenden Prozeß gesandt, das ihn
bittet sich zu beenden. Dieses Signal heißt SIGINT (für SIGnal INTerrupt) und bittet sich zu beenden. Dieses Signal heißt SIGINT (für SIGnal INTerrupt) und
trägt die Nummer 2. Das kann ein kleines Problem darstellen, wenn das Skript trägt die Nummer 2. Das kann ein kleines Problem darstellen, wenn das Skript
@ -342,7 +404,7 @@ der Aufrufsyntax auf die Standard-Fehlerausgabe geschrieben.
Wir wollen uns einen MP3-Player programmieren, der Alle MP3-Dateien aus einem Wir wollen uns einen MP3-Player programmieren, der Alle MP3-Dateien aus einem
bestimmten Verzeichnisbaum in zufälliger Reihenfolge abspielt. Damit dieses bestimmten Verzeichnisbaum in zufälliger Reihenfolge abspielt. Damit dieses
Problem für uns eine Herausforderung darstellt\footnote{Denn schließlich hat 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 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 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 Ausgabe per \texttt{echo} ist, oder ob der Name per Sprachsynthese oder auf
einem externen Display angezeigt werden soll ist an dieser Stelle egal. einem externen Display angezeigt werden soll ist an dieser Stelle egal.
@ -452,7 +514,7 @@ Ausgabe von \texttt{ps} erscheint das \texttt{grep}-Kommando allerdings mit
\subsection{Dateiinhalte suchen}\label{beispiele_suchen_dateien}\index{find=\texttt{find}|(textbf} \subsection{Dateiinhalte suchen}\label{beispiele_suchen_dateien}\index{find=\texttt{find}|(textbf}
Ein weiterer wertvoller Trick, diesmal im Zusammenhang mit \texttt{find} ist Ein weiterer wertvoller Trick, diesmal im Zusammenhang mit \texttt{find}, ist
folgendes Szenario: Es gibt ein Verzeichnis mit vielen Unterverzeichnissen, folgendes Szenario: Es gibt ein Verzeichnis mit vielen Unterverzeichnissen,
überall liegen Perl-Skripte und andere Dateien. Gesucht sind alle Dateien, in überall liegen Perl-Skripte und andere Dateien. Gesucht sind alle Dateien, in
denen eine Zeile mit dem Inhalt `strict' vorkommt. Man könnte jetzt denen eine Zeile mit dem Inhalt `strict' vorkommt. Man könnte jetzt
@ -468,10 +530,10 @@ alle Dateien, die dem Muster entsprechen:
\lstinline|grep -r strict *.pl| \lstinline|grep -r strict *.pl|
Das führt wieder nicht zu dem gewünschten Ergebnis. Da die Unterverzeichnisse Und wieder führt es nicht zu dem gewünschten Ergebnis. Da die
nicht die Extension `*.pl' tragen, werden sie nicht berücksichtigt. Für die Unterverzeichnisse nicht die Extension `*.pl' tragen, werden sie nicht
Suche in Unterverzeichnissen ziehen wir \texttt{find} (Siehe Abschnitt berücksichtigt. Für die Suche in Unterverzeichnissen ziehen wir \texttt{find}
\ref{find}) heran: (Siehe Abschnitt \ref{find}) heran:
\lstinline|find . -name \*.pl -exec grep strict {} \;| \lstinline|find . -name \*.pl -exec grep strict {} \;|

View File

@ -10,6 +10,8 @@
\item Von DOS nach Linux HOWTO (\href{http://www.linuxhaven.de/dlhp/HOWTO/DE-DOS-nach-Linux-HOWTO.html}{http://www.linuxhaven.de/dlhp/HOWTO/DE-DOS-nach-Linux-HOWTO.html}) \item Von DOS nach Linux HOWTO (\href{http://www.linuxhaven.de/dlhp/HOWTO/DE-DOS-nach-Linux-HOWTO.html}{http://www.linuxhaven.de/dlhp/HOWTO/DE-DOS-nach-Linux-HOWTO.html})
\item Bash Guide for Beginners (\href{http://tldp.org/LDP/Bash-Beginners-Guide/}{http://tldp.org/LDP/Bash-Beginners-Guide/}) \item Bash Guide for Beginners (\href{http://tldp.org/LDP/Bash-Beginners-Guide/}{http://tldp.org/LDP/Bash-Beginners-Guide/})
\item Advanced Bash-Scripting Guide (\href{http://tldp.org/LDP/abs/}{http://tldp.org/LDP/abs/}) \item Advanced Bash-Scripting Guide (\href{http://tldp.org/LDP/abs/}{http://tldp.org/LDP/abs/})
\item The Open Group Base Specifications
\item Single Unix Specifications V2
\item ... und eine Menge Skripte, die ich im Laufe der Zeit gelesen habe (das \item ... und eine Menge Skripte, die ich im Laufe der Zeit gelesen habe (das
kann ich nur jedem empfehlen - es ist spannender als es sich anhört...). kann ich nur jedem empfehlen - es ist spannender als es sich anhört...).
\end{itemize} \end{itemize}

View File

@ -83,7 +83,7 @@ Der Weg in die andere Richtung ist ganz
\lstinline_tar cf - datei.txt | ssh 192.168.2.1 "(mkdir -p $PWD ;cd $PWD; tar xf -)"_ \lstinline_tar cf - datei.txt | ssh 192.168.2.1 "(mkdir -p $PWD ;cd $PWD; tar xf -)"_
Hier wird die Datei verpackt und versendet. Eine Besonderheit gegenüber dem Hier wird die Datei verpackt und versendet. Eine Besonderheit gegenüber dem
vorigen Beispiel bestehtdarin, daß das Zielverzeichnis bei Bedarf erstellt vorigen Beispiel besteht darin, daß das Zielverzeichnis bei Bedarf erstellt
wird, bevor die Datei dort entpackt wird. Zur Erklärung: Die Variable wird, bevor die Datei dort entpackt wird. Zur Erklärung: Die Variable
\texttt{\$PWD} wird, da sie nicht von Ticks `gesichert' wird, schon lokal durch \texttt{\$PWD} wird, da sie nicht von Ticks `gesichert' wird, schon lokal durch
die Shell expandiert. An dieser Stelle erscheint also auf dem entfernten System die Shell expandiert. An dieser Stelle erscheint also auf dem entfernten System
@ -195,74 +195,24 @@ sechs Kilobytes~--~
Um es nochmal zu betonen: Diese beiden Methoden sind mit Vorsicht zu genießen. Um es nochmal zu betonen: Diese beiden Methoden sind mit Vorsicht zu genießen.
Bei der ersten führt jede zusätzliche oder gelöschte Zeile zu einer kaputten Bei der ersten führt jede zusätzliche oder gelöschte Zeile zu einer kaputten
Ausgabedatei, bei der zweiten reichen schon einzelne Zeilen. In jedem Fall Ausgabedatei, bei der zweiten reichen schon einzelne Zeichen. In jedem Fall
sollte nach dem Auspacken noch einmal mittels \texttt{sum} oder \texttt{md5sum} sollte nach dem Auspacken noch einmal mittels \texttt{sum} oder \texttt{md5sum}
eine Checksumme gezogen und verglichen werden. eine Checksumme gezogen und verglichen werden.
\section{Dateien, die es nicht gibt} \section{Dateien, die es nicht gibt}
TODO!!! Dateien, die es nicht gibt Eine Eigenart der Behandlung von Dateien unter Unix besteht im Verhalten beim
Löschen. Gelöscht wird nämlich zunächst nur der Inode, also die Markierung im
Dateisystem unter der die Datei gefunden werden kann. Physikalisch besteht die
Datei noch, sie wird lediglich im Verzeichnis nicht mehr angezeigt.
\subsection{Speichern in nicht existente Dateien} Hat ein Prozeß die Datei noch in irgendeiner Form geöffnet, kann er weiter
darauf zugreifen. Erst wenn er die Datei schließt ist sie tatsächlich und
unwiederbringlich `weg'.
TODO!!! Speichern in nicht existente Dateien Dieser Effekt der `nicht existenten Dateien' läßt sich an verschiedenen Stellen
geschickt einsetzen.
\subsection{Subshell-Schleifen vermeiden}\label{subshellschleifen}
Wir wollen ein Skript schreiben, das die \texttt{/etc/passwd} liest und dabei
zählt, wie viele Benutzer eine UID kleiner als 100 haben.
Folgendes Skript funktioniert nicht:
\begin{lstlisting}
#!/bin/sh
count=0
cat /etc/passwd | while read i; do
uid=`echo $i | cut -f 3 -d:`
if [ $uid -lt 100 ]; then
count=`expr $count + 1`
echo $count
fi
done
echo Es sind $count Benutzer mit einer ID kleiner 100 eingetragen
\end{lstlisting}
Was ist passiert?
Dieses Skript besteht im Wesentlichen aus einer Pipe. Wir haben ein
\texttt{cat}-Kom\-man\-do, das den Inhalt der \texttt{/etc/passwd} durch eben
diese Pipe an eine Schleife übergibt. Das \texttt{read}-Kommando in der
Schleife liest die einzelnen Zeilen aus, dann folgt ein Bißchen Auswertung.
Es ist zu beobachten, daß bei der Ausgabe in Zeile 7 die Variable
\texttt{\$count} korrekte Werte enthält. Um so unverständlicher ist es, daß sie
nach der Vollendung der Schleife wieder den Wert 0 enthält.
Das liegt daran, daß diese Schleife als Teil einer Pipe in einer Subshell
ausgeführt wird. Die Variable \texttt{\$count} steht damit in der Schleife
praktisch nur lokal zur Verfügung, sie wird nicht an das umgebende Skript
`hochgereicht'.
Neben der Methode in \ref{daten_hochreichen} bietet sich hier eine viel
einfachere Lösung an:
\begin{lstlisting}
#!/bin/sh
count=0
while read i; do
uid=`echo $i | cut -f 3 -d:`
if [ $uid -lt 100 ]; then
count=`expr $count + 1`
echo $count
fi
done < /etc/passwd
echo Es sind $count Benutzer mit einer ID kleiner 100 eingetragen
\end{lstlisting}
Hier befindet sich die Schleife nicht in einer Pipe, daher wird sie auch nicht
in einer Subshell ausgeführt. Man kann auf das \texttt{cat}-Kommando verzichten
und den Inhalt der Datei durch die Umlenkung in Zeile 9 direkt auf die
Standardeingabe der Schleife (und somit auf das \texttt{read}-Kommando) legen.
\subsection{Daten aus einer Subshell hochreichen}\label{daten_hochreichen} \subsection{Daten aus einer Subshell hochreichen}\label{daten_hochreichen}
@ -297,7 +247,7 @@ geht man in solchen F
Bei einfachen Zahlenwerten könnte beispielsweise ein Rückgabewert helfen. Bei einfachen Zahlenwerten könnte beispielsweise ein Rückgabewert helfen.
Komplexere Informationen können in eine temporäre Datei geschrieben werden, die Komplexere Informationen können in eine temporäre Datei geschrieben werden, die
danach geparst werden müßte. Wenn die Informationen in Zeilen der Form danach geparst werden müßte. Wenn die Informationen in Zeilen der Form
`VARIABLE=\dq{}Wert\dq{}' gespeichert werden, kann die Datei einfach mittels \lstinline|VARIABLE="Wert"| gespeichert werden, kann die Datei einfach mittels
\texttt{source} (Abschnitt \ref{source}) oder einem Konstrukt der Art \texttt{source} (Abschnitt \ref{source}) oder einem Konstrukt der Art
\texttt{eval `cat tempfile`} gelesen werden. \texttt{eval `cat tempfile`} gelesen werden.

View File

@ -15,7 +15,7 @@
headsepline, % Trennlinie unter die Kopfzeile headsepline, % Trennlinie unter die Kopfzeile
pointlessnumbers, % Keine Punkte hinter den pointlessnumbers, % Keine Punkte hinter den
% Gliederungsnummern % Gliederungsnummern
% halfparskip, % Abstände zwischen den Absätzen, statt halfparskip, % Abstände zwischen den Absätzen, statt
% Einrückung der ersten Zeile % Einrückung der ersten Zeile
% draft, % Entwurfsmodus % draft, % Entwurfsmodus
final, % Release-Modus final, % Release-Modus
@ -51,10 +51,8 @@
\lstset{ \lstset{
extendedchars=true, extendedchars=true,
backgroundcolor=\color[gray]{0.95}, backgroundcolor=\color[gray]{0.95},
%basicstyle=\ttfamily\scriptsize,
basicstyle=\ttfamily\footnotesize, basicstyle=\ttfamily\footnotesize,
numbers=left, numbers=left,
%numberstyle=\tiny,
numberstyle=\scriptsize, numberstyle=\scriptsize,
stepnumber=2, stepnumber=2,
numbersep=5pt numbersep=5pt
@ -93,12 +91,13 @@
\begin{document} % hiermit muß jedes Dokument beginnen \begin{document} % hiermit muß jedes Dokument beginnen
\vspace*{.75in} % Die Titelseite \vspace*{.6in} % Die Titelseite
\thispagestyle{empty} \thispagestyle{empty}
\begin{centering} \begin{centering}
\rule{5in}{.04in}\\ \vspace{.25in} \rule{5in}{.04in}\\ \vspace{.25in}
\Huge {\bf SHELL\\ \vspace{.4in} PROGRAMMIERUNG}\\ \vspace{.1in} \Huge {\bf SHELL\\ \vspace{.4in} PROGRAMMIERUNG}\\ \vspace{.1in}
\rule{5in}{.04in}\\ \vspace{.5in} \rule{5in}{.04in}\\ \vspace{.6in}
\large v2.0.0 RC1\\
\large \today\\ \vspace{.75in} \large \today\\ \vspace{.75in}
\large von\\ \vspace{.3in} \large von\\ \vspace{.3in}
\LARGE {\bf Ronald Schaten} \\ \vspace{.6in} \LARGE {\bf Ronald Schaten} \\ \vspace{.6in}
@ -109,40 +108,29 @@
\thispagestyle{empty} % eine Leerseite \thispagestyle{empty} % eine Leerseite
~\vfill ~\vfill
%\fboxsep 1.36mm % Syntax-Boxen (sybox) definieren:
%\definecolor{g1}{gray}{0.92} TODO: Breite der sybox anpassen
%\newsavebox{\syntaxbox} \fboxsep 1.36mm
%\newenvironment{sybox} \definecolor{g1}{gray}{0.95}
%{\begin{lrbox}{\syntaxbox} \newsavebox{\syntaxbox}
%\begin{minipage}{12.5cm}} \newenvironment{sybox}
%{\end{minipage} {\begin{lrbox}{\syntaxbox}
%\end{lrbox} \begin{minipage}{\textwidth}}
%{\fcolorbox{g1}{g1} {\end{minipage}
%{\parbox{12.5cm}{\usebox{\syntaxbox}\hfill\hbox{}}}}} \end{lrbox}
% {\fcolorbox{g1}{g1}
%\begin{sybox} {\parbox{\textwidth}{\usebox{\syntaxbox}\hfill\hbox{}}}}}
%Syntaxbox, in der Sonderzeichen wie \verb?%~^? dargestellt werden können.
%
%Dieses Dokument ist entstanden, weil ich für mich selbst eine kompakte
%Übersicht zu diesem Thema haben wollte. Ich beabsichtige nicht, damit in
%irgendeiner Form Kommerz zu machen. Ich stelle es frei zur Verfügung, in der
%Hoffnung, daß andere Leute daraus vielleicht einen Nutzen ziehen können.
%\textbf{Aber ich übernehme keine Garantie für die Korrektheit der hier
%dargestellten Dinge.} Mit der Formulierung \textsl{`daraus vielleicht einen
%Nutzen ziehen können'} meine ich nicht, daß dieses Dokument~--~oder Teile
%daraus~--~verkauft werden darf. \textbf{Dieses Dokument darf nur kostenlos
%weitergegeben werden.}
%\end{sybox}
\footnotesize \footnotesize
Copyright \copyright{} 2000-2005 Ronald Schaten (ronald@schatenseite.de)\bigskip Copyright \copyright{} 2000-2005 Ronald Schaten (ronald@schatenseite.de)
TODO: Vernünftige Lizenz einsetzen!\bigskip TODO: Vernünftige Lizenz einsetzen!
%\texttt{${}$Id${}$}\bigskip %\texttt{${}$Id${}$}
Die aktuellste Version dieses Dokumentes befindet sich auf Die aktuellste Version dieses Dokumentes befindet sich auf
\href{http://www.schatenseite.de/}{http://www.schatenseite.de/}.\bigskip \href{http://www.schatenseite.de/}{http://www.schatenseite.de/}.
Dieses Dokument ist entstanden, weil ich für mich selbst eine kompakte Dieses Dokument ist entstanden, weil ich für mich selbst eine kompakte
Übersicht zu diesem Thema haben wollte. Ich beabsichtige nicht, damit in Übersicht zu diesem Thema haben wollte. Ich beabsichtige nicht, damit in
@ -152,7 +140,7 @@ Hoffnung, da
dargestellten Dinge.} Mit der Formulierung \textsl{`daraus vielleicht einen dargestellten Dinge.} Mit der Formulierung \textsl{`daraus vielleicht einen
Nutzen ziehen können'} meine ich nicht, daß dieses Dokument~--~oder Teile Nutzen ziehen können'} meine ich nicht, daß dieses Dokument~--~oder Teile
daraus~--~verkauft werden darf. \textbf{Dieses Dokument darf nur kostenlos daraus~--~verkauft werden darf. \textbf{Dieses Dokument darf nur kostenlos
weitergegeben werden.}\bigskip weitergegeben werden.}
Ich danke folgenden Personen, die mir bei der Durchsicht behilflich waren und Ich danke folgenden Personen, die mir bei der Durchsicht behilflich waren und
durch ihre konstruktive Kritik zu Verbesserungen beigetragen haben (in durch ihre konstruktive Kritik zu Verbesserungen beigetragen haben (in
@ -169,7 +157,7 @@ chronologischer Reihenfolge ihres Eingreifens):
Und ich bitte alle Leser, auf eventuelle Fehler zu achten und mich darauf Und ich bitte alle Leser, auf eventuelle Fehler zu achten und mich darauf
aufmerksam zu machen. Auch abgesehen davon freue ich mich über jede aufmerksam zu machen. Auch abgesehen davon freue ich mich über jede
Rückmeldung.\bigskip Rückmeldung.
Dieses Dokument entstand unter Verwendung von Linux, vim und \LaTeX. Dank an Dieses Dokument entstand unter Verwendung von Linux, vim und \LaTeX. Dank an
deren Entwickler. deren Entwickler.
@ -184,10 +172,10 @@ deren Entwickler.
\pagenumbering{arabic} \pagenumbering{arabic}
% Haupttextteil % Haupttextteil
\include{was_ist_die_shell} \include{was_ist_die_shell}
\include{wo_sind_unterschiede_zu_dos_batchdateien}
\include{wofuer_shell_programmierung} \include{wofuer_shell_programmierung}
\include{wie_sieht_ein_shell_skript_aus} \include{wie_sieht_ein_shell_skript_aus}
\include{werkzeugkasten} \include{werkzeugkasten}
\include{wo_sind_unterschiede_zu_dos_batchdateien}
\appendix \appendix
\include{beispiele} \include{beispiele}
\include{schmutzige_tricks} \include{schmutzige_tricks}

View File

@ -1,30 +0,0 @@
% $Id$
\begin{longtable}{|X l|}
% KILLED & LINE!!!! \kill
\hline
\endfirsthead
\endhead
\endfoot
\hline
\endlastfoot
\multicolumn{2}{|X|}{\textsl{Seitenweises Formatieren der Dateien, die auf der Befehlszeile angegeben wurden, und speichern des jeweiligen Ergebnisses:}} \\
\multicolumn{2}{|X|}{\texttt{for file do}} \\
\multicolumn{2}{|X|}{\texttt{~pr \$file > \$file.tmp~~\# pr: Formatiert Textdateien}\index{!>=\texttt{!>}}} \\
\multicolumn{2}{|X|}{\texttt{done}} \\
\multicolumn{2}{|X|}{\STRUT\textsl{Durchsuche Kapitel zur Erstellung einer Wortliste (wie \texttt{fgrep -f}):}} \\
\multicolumn{2}{|X|}{\texttt{for item in `cat program\_list`~~\# cat: Datei ausgeben}\index{cat=\texttt{cat}}\index{Backticks}} \\
\multicolumn{2}{|X|}{\texttt{do}} \\
\multicolumn{2}{|X|}{\texttt{~echo \dq Pruefung der Kapitel auf\dq}\index{Anführungszeichen}} \\
\multicolumn{2}{|X|}{\texttt{~echo \dq Referenzen zum Programm \$item ...\dq}\index{Anführungszeichen}} \\
\multicolumn{2}{|X|}{\texttt{~grep -c \dq\$item.[co]\dq~chap*~~\# grep: nach Muster\index{Mustererkennung} suchen}\index{[abc]=\texttt{[}\textsl{abc}\texttt{]}}\index{Anführungszeichen}\index{grep=\texttt{grep}}} \\
\multicolumn{2}{|X|}{\texttt{done}} \\
\multicolumn{2}{|X|}{\STRUT\textsl{Ermittle einen Ein-Wort-Titel aus jeder Datei und verwende ihn als neuen Dateinamen:}} \\
\multicolumn{2}{|X|}{\texttt{for file do}} \\
\multicolumn{2}{|X|}{\texttt{~name=`sed -n 's/NAME: //p' \$file`}\index{!==\texttt{!=}}\index{Backticks}\index{Ticks}} \\
\multicolumn{2}{|X|}{\texttt{~~~~~~~~~~\# sed: Skriptsprache zur}\index{sed=\texttt{sed}}} \\
\multicolumn{2}{|X|}{\texttt{~~~~~~~~~~\# Textformatierung}} \\
\multicolumn{2}{|X|}{\texttt{~mv \$file \$name~~\# mv: Datei verschieben}} \\
\multicolumn{2}{|X|}{\texttt{~~~~~~~~~~~~~~~~~\# bzw. umbenennen}} \\
\multicolumn{2}{|X|}{\texttt{done}} \\
\end{longtable}

View File

@ -1,17 +0,0 @@
% $Id$
\begin{longtable}{|X l|}
% KILLED & LINE!!!! \kill
\hline
\endfirsthead
\endhead
\endfoot
\hline
\endlastfoot
\multicolumn{2}{|X|}{\texttt{count () \{}} \\
\multicolumn{2}{|X|}{\texttt{~ls -1 | wc -l~~\# ls: Liste aller Dateien im Verzeichnis}\index{Pipe}} \\
\multicolumn{2}{|X|}{\texttt{~~~~~~~~~~~~~~~~\#~~~~~Mit Parameter -1 einspaltig}} \\
\multicolumn{2}{|X|}{\texttt{~~~~~~~~~~~~~~~~\# wc: Word-Count, zählt Wörter}\index{wc=\texttt{wc}}} \\
\multicolumn{2}{|X|}{\texttt{~~~~~~~~~~~~~~~~\#~~~~~Mit Parameter -l Zeilen}} \\
\multicolumn{2}{|X|}{\texttt{\}}} \\
\end{longtable}

View File

@ -1,17 +0,0 @@
% $Id$
\begin{longtable}{|X l|}
% KILLED & LINE!!!! \kill
\hline
\endfirsthead
\endhead
\endfoot
\hline
\endlastfoot
\multicolumn{2}{|X|}{\textsl{Füge eine 0 vor Zahlen kleiner 10 ein:}} \\
\multicolumn{2}{|X|}{\texttt{if [ \$counter -lt 10 ]; then}\index{;=\texttt{;}}} \\
\multicolumn{2}{|X|}{\texttt{~number=0\$counter; else number=\$counter; fi}\index{!==\texttt{!=}}} \\
\multicolumn{2}{|X|}{\STRUT\textsl{Lösche ein Verzeichnis, wenn es existiert:}} \\
\multicolumn{2}{|X|}{\texttt{if [ -d \$dir ]; then}\index{!!=\texttt{!!}}\index{;=\texttt{;}}} \\
\multicolumn{2}{|X|}{\texttt{~rmdir \$dir; fi~~\# rmdir: Verzeichnis löschen}} \\
\end{longtable}

View File

@ -1,24 +0,0 @@
% $Id$
\begin{longtable}{|X l|}
% KILLED & LINE!!!! \kill
\hline
\endfirsthead
\endhead
\endfoot
\hline
\endlastfoot
\multicolumn{2}{|X|}{\texttt{\$ mkdir /usr/local/src/bash/\{old,new,dist,bugs\}}} \\
\multicolumn{2}{|X|}{Erzeugt die Verzeichnisse} \\
\multicolumn{2}{|X|}{\textit{/usr/local/src/bash/old}} \\
\multicolumn{2}{|X|}{\textit{/usr/local/src/bash/new}} \\
\multicolumn{2}{|X|}{\textit{/usr/local/src/bash/dist}} \\
\multicolumn{2}{|X|}{\textit{/usr/local/src/bash/bugs}} \\
\multicolumn{2}{|X|}{\STRUT\texttt{\$ chown root /usr/\{ucb/\{ex,edit\},lib/\{ex?.?*,how\b{ }ex\}\}}} \\
\multicolumn{2}{|X|}{Weist die folgenden Dateien / Verzeichnisse dem Benutzer root zu:} \\
\multicolumn{2}{|X|}{\textit{/usr/ucb/ex}} \\
\multicolumn{2}{|X|}{\textit{/usr/ucb/edit}} \\
\multicolumn{2}{|X|}{\textit{/usr/lib/ex?.?*}} \\
\multicolumn{2}{|X|}{\textit{/usr/lib/how\b{ }ex}} \\
\multicolumn{2}{|X|}{Dabei wird \textit{/usr/lib/ex?.?*} noch weiter expandiert.} \\
\end{longtable}

View File

@ -1,14 +0,0 @@
% $Id$
\begin{longtable}{|l|X|}
% KILLED & LINE!!!! \kill
\hline
\endfirsthead
\endhead
\endfoot
\hline
\endlastfoot
\texttt{\$ ls neu*} & Listet alle Dateien, die mit `neu' anfangen \tabularnewline\STRUT
\texttt{\$ ls neu?} & Listet `neuX', `neu4', aber nicht `neu10' \tabularnewline\STRUT
\texttt{\$ ls [D-R]*} & Listet alle Dateien, die mit einem Großbuchstaben\index{Großbuchstaben}\footnote{Natürlich wird in Shell-Skripten~--~wie (fast) überall in der Unix-Welt~--~zwischen Groß- und Kleinschreibung unterschieden.} zwischen D und R anfangen
\end{longtable}

View File

@ -1,19 +0,0 @@
% $Id$
\begin{longtable}{|X l|}
% KILLED & LINE!!!! \kill
\hline
\endfirsthead
\endhead
\endfoot
\hline
\endlastfoot
\multicolumn{2}{|X|}{\texttt{\$ echo 'Ticks \dq schützen\dq~Anführungszeichen'}} \\
\multicolumn{2}{|X|}{\texttt{Ticks \dq schützen\dq~Anführungszeichen}} \\
\multicolumn{2}{|X|}{\STRUT\texttt{\$ echo \dq Ist dies ein \textbackslash\dq Sonderfall\textbackslash\dq ?\dq}} \\
\multicolumn{2}{|X|}{\texttt{Ist dies ein \dq Sonderfall\dq ?}} \\
\multicolumn{2}{|X|}{\STRUT\texttt{\$ echo \dq Sie haben `ls | wc -l` Dateien in `pwd`\dq}\index{wc=\texttt{wc}}} \\
\multicolumn{2}{|X|}{\texttt{Sie haben 43 Dateien in /home/rschaten}} \\
\multicolumn{2}{|X|}{\STRUT\texttt{\$ echo \dq Der Wert von \textbackslash\$x ist \$x\dq}} \\
\multicolumn{2}{|X|}{\texttt{Der Wert von \$x ist 100}} \\
\end{longtable}

View File

@ -1,18 +0,0 @@
% $Id$
\begin{longtable}{|X l|}
% KILLED & LINE!!!! \kill
\hline
\endfirsthead
\endhead
\endfoot
\hline
\endlastfoot
\multicolumn{2}{|X|}{\textsl{Warten, bis sich der Administrator einloggt:}} \\
\multicolumn{2}{|X|}{\texttt{until who | grep \dq root\dq; do}\index{;=\texttt{;}}\index{Anführungszeichen}\index{who=\texttt{who}}} \\
\multicolumn{2}{|X|}{\texttt{~~~~~~~~~~\# who: Liste der Benutzer}} \\
\multicolumn{2}{|X|}{\texttt{~~~~~~~~~~\# grep: Suchen nach Muster}\index{Mustererkennung}} \\
\multicolumn{2}{|X|}{\texttt{~sleep 2~~\# sleep: warten}\index{sleep=\texttt{sleep}}} \\
\multicolumn{2}{|X|}{\texttt{done}} \\
\multicolumn{2}{|X|}{\texttt{echo \dq Der Meister ist anwesend\dq}\index{Anführungszeichen}} \\
\end{longtable}

View File

@ -11,7 +11,7 @@
\texttt{\$ \textsl{h}=\textsl{hoch} \textsl{r}=\textsl{runter} \textsl{l}=} & Weist den drei Variablen Werte zu, wobei \textsl{l} einen leeren Wert erhält. \tabularnewline\STRUT \texttt{\$ \textsl{h}=\textsl{hoch} \textsl{r}=\textsl{runter} \textsl{l}=} & Weist den drei Variablen Werte zu, wobei \textsl{l} einen leeren Wert erhält. \tabularnewline\STRUT
\texttt{\$ echo \$\{h\}sprung} & Gibt \textsl{hochsprung} aus. Die Klammern müssen gesetzt werden, damit \textsl{h} als Variablenname erkannt werden kann. \tabularnewline\STRUT \texttt{\$ echo \$\{h\}sprung} & Gibt \textsl{hochsprung} aus. Die Klammern müssen gesetzt werden, damit \textsl{h} als Variablenname erkannt werden kann. \tabularnewline\STRUT
\texttt{\$ echo \$\{h-\$r\}} & Gibt \textsl{hoch} aus, da die Variable \textsl{h} belegt ist. Ansonsten würde der Wert von \textsl{r} ausgegeben. \tabularnewline\STRUT \texttt{\$ echo \$\{h-\$r\}} & Gibt \textsl{hoch} aus, da die Variable \textsl{h} belegt ist. Ansonsten würde der Wert von \textsl{r} ausgegeben. \tabularnewline\STRUT
\texttt{\$ echo \$\{tmp-`date`\}} & Gibt das aktuelle Datum aus, wenn die Variable \textsl{tmp} nicht gesetzt ist.\footnote{Der Befehl \texttt{date} gibt das Datum zurück.} \tabularnewline\STRUT \texttt{\$ echo \$\{tmp-`date`\}} & Gibt das aktuelle Datum aus, wenn die Variable \textsl{tmp} nicht gesetzt ist. \tabularnewline\STRUT
\texttt{\$ echo \$\{l:=\$r\}} & Gibt \textsl{runter} aus, da die Variable \textsl{l} keinen Wert enthält. Gleichzeitig wird \textsl{l} der Wert von \textsl{r} zugewiesen. \tabularnewline\STRUT \texttt{\$ echo \$\{l:=\$r\}} & Gibt \textsl{runter} aus, da die Variable \textsl{l} keinen Wert enthält. Gleichzeitig wird \textsl{l} der Wert von \textsl{r} zugewiesen. \tabularnewline\STRUT
\texttt{\$ echo \$l} & Gibt \textsl{runter} aus, da \textsl{l} jetzt den gleichen Inhalt hat wie \textsl{r}. \texttt{\$ echo \$l} & Gibt \textsl{runter} aus, da \textsl{l} jetzt den gleichen Inhalt hat wie \textsl{r}.
\end{longtable} \end{longtable}

View File

@ -1,12 +0,0 @@
% $Id$
\begin{longtable}{|X l|}
% KILLED & LINE!!!! \kill
\hline
\endfirsthead
\endhead
\endfoot
\hline
\endlastfoot
\multicolumn{2}{|X|}{\texttt{break }\textsl{[ n ]}} \\
\end{longtable}

View File

@ -1,16 +0,0 @@
% $Id$
\begin{longtable}{|X l|}
% KILLED & LINE!!!! \kill
\hline
\endfirsthead
\endhead
\endfoot
\hline
\endlastfoot
\multicolumn{2}{|X|}{\texttt{case }\textsl{Wert}\texttt{ in}} \\
\multicolumn{2}{|X|}{\texttt{~}\textsl{Muster1}\texttt{) }\textsl{Befehle1}\texttt{;;}} \\
\multicolumn{2}{|X|}{\texttt{~}\textsl{Muster2}\texttt{) }\textsl{Befehle2}\texttt{;;}} \\
\multicolumn{2}{|X|}{\texttt{~\vdots}} \\
\multicolumn{2}{|X|}{\texttt{esac}} \\
\end{longtable}

View File

@ -1,12 +0,0 @@
% $Id$
\begin{longtable}{|X l|}
% KILLED & LINE!!!! \kill
\hline
\endfirsthead
\endhead
\endfoot
\hline
\endlastfoot
\multicolumn{2}{|X|}{\texttt{continue }\textsl{[ n ]}} \\
\end{longtable}

View File

@ -1,12 +0,0 @@
% $Id$
\begin{longtable}{|X l|}
% KILLED & LINE!!!! \kill
\hline
\endfirsthead
\endhead
\endfoot
\hline
\endlastfoot
\multicolumn{2}{|X|}{\texttt{exit }\textsl{[ n ]}} \\
\end{longtable}

View File

@ -1,15 +0,0 @@
% $Id$
\begin{longtable}{|X l|}
% KILLED & LINE!!!! \kill
\hline
\endfirsthead
\endhead
\endfoot
\hline
\endlastfoot
\multicolumn{2}{|X|}{\texttt{for }\textsl{x [}\texttt{ in }\textsl{Liste ]}} \\
\multicolumn{2}{|X|}{\texttt{do}} \\
\multicolumn{2}{|X|}{\texttt{~}\textsl{Befehle}} \\
\multicolumn{2}{|X|}{\texttt{done}} \\
\end{longtable}

View File

@ -1,18 +0,0 @@
% $Id$
\begin{longtable}{|X l|}
% KILLED & LINE!!!! \kill
\hline
\endfirsthead
\endhead
\endfoot
\hline
\endlastfoot
\multicolumn{2}{|X|}{\texttt{if }\textsl{Bedingung1}} \\
\multicolumn{2}{|X|}{\texttt{then }\textsl{Befehle1}} \\
\multicolumn{2}{|X|}{\textsl{[}\texttt{ elif }\textsl{Bedingung2}} \\
\multicolumn{2}{|X|}{\texttt{ then }\textsl{Befehle2 ]}} \\
\multicolumn{2}{|X|}{\texttt{ \vdots}} \\
\multicolumn{2}{|X|}{\textsl{[}\texttt{ else }\textsl{Befehle3 ]}} \\
\multicolumn{2}{|X|}{\texttt{fi}} \\
\end{longtable}

View File

@ -14,7 +14,7 @@
\texttt{|} & Pipe \tabularnewline\STRUT \texttt{|} & Pipe \tabularnewline\STRUT
\texttt{< > >\&} & Umlenkungssymbole \tabularnewline\STRUT \texttt{< > >\&} & Umlenkungssymbole \tabularnewline\STRUT
\texttt{* ? [ ] \~{} + - @ !} & Meta-Zeichen\index{Meta-Zeichen} für Dateinamen \tabularnewline\STRUT \texttt{* ? [ ] \~{} + - @ !} & Meta-Zeichen\index{Meta-Zeichen} für Dateinamen \tabularnewline\STRUT
\texttt{` ` }(Backticks oder Single Backquotes\footnote{Man erhält sie durch \Ovalbox{SHIFT} und die Taste neben dem Backspace.}) & Befehls-Substitution\index{Befehls>-Substitution} \tabularnewline\STRUT \texttt{` ` }(Backticks oder Single Backquotes\footnote{Man erhält sie üblicherweise durch \Ovalbox{SHIFT} und die Taste neben dem Backspace.}) & Befehls-Substitution\index{Befehls>-Substitution} \tabularnewline\STRUT
\texttt{\$} & Variablen-Substitution\index{Variablen>-Substitution} \tabularnewline\STRUT \texttt{\$} & Variablen-Substitution\index{Variablen>-Substitution} \tabularnewline\STRUT
\texttt{\Ovalbox{NEWLINE} \Ovalbox{SPACE} \Ovalbox{TAB}} & \texttt{\Ovalbox{NEWLINE} \Ovalbox{SPACE} \Ovalbox{TAB}} &
Wort-Trennzeichen\footnote{Die Wort-Trennzeichen sind in der vordefinierten Variable \texttt{\$IFS} abgelegt. Siehe Abschnitt \ref{vordefinierte_variablen}.} Wort-Trennzeichen\footnote{Die Wort-Trennzeichen sind in der vordefinierten Variable \texttt{\$IFS} abgelegt. Siehe Abschnitt \ref{vordefinierte_variablen}.}

View File

@ -19,7 +19,7 @@ Ausnahme eines weiteren \texttt{'} oder eines Backslashes
(\texttt{\textbackslash}) \tabularnewline\STRUT (\texttt{\textbackslash}) \tabularnewline\STRUT
\texttt{\textbackslash} & (Backslash\index{Backslash}) Das Zeichen nach einem \texttt{\textbackslash} & (Backslash\index{Backslash}) Das Zeichen nach einem
\textbackslash wird wörtlich genommen. Anwendung z. B. innerhalb von \textbackslash wird wörtlich genommen. Anwendung z.~B. innerhalb von
\texttt{\dq~\dq}, um \texttt{\dq}, \texttt{\$} und \texttt{`} zu entwerten. \texttt{\dq~\dq}, um \texttt{\dq}, \texttt{\$} und \texttt{`} zu entwerten.
Häufig verwendet zur Angabe von Leerzeichen (space) und Zeilenendezeichen, oder Häufig verwendet zur Angabe von Leerzeichen (space) und Zeilenendezeichen, oder
um ein \textbackslash -Zeichen selbst anzugeben. um ein \textbackslash -Zeichen selbst anzugeben.

View File

@ -1,12 +0,0 @@
% $Id$
\begin{longtable}{|X l|}
% KILLED & LINE!!!! \kill
\hline
\endfirsthead
\endhead
\endfoot
\hline
\endlastfoot
\multicolumn{2}{|X|}{\texttt{return }\textsl{[ n ]}} \\
\end{longtable}

View File

@ -12,6 +12,6 @@ Nummer & Name & Bedeutung \\
0 & Normal Exit & Wird durch das \texttt{exit}\index{exit=\texttt{exit}}-Kommando ausgelöst. \tabularnewline\STRUT 0 & Normal Exit & Wird durch das \texttt{exit}\index{exit=\texttt{exit}}-Kommando ausgelöst. \tabularnewline\STRUT
1 & SIGHUP & Wenn die Verbindung abbricht (z. B. wenn das Terminal geschlossen wird). \tabularnewline\STRUT 1 & SIGHUP & Wenn die Verbindung abbricht (z. B. wenn das Terminal geschlossen wird). \tabularnewline\STRUT
2 & SIGINT & Zeigt einen Interrupt an (\Ovalbox{CTRL}-\Ovalbox{C}). \tabularnewline\STRUT 2 & SIGINT & Zeigt einen Interrupt an (\Ovalbox{CTRL}+\Ovalbox{C}). \tabularnewline\STRUT
15 & SIGTERM & Wird vom \texttt{kill}\index{kill=\texttt{kill}}-Kommando gesendet. 15 & SIGTERM & Wird vom \texttt{kill}\index{kill=\texttt{kill}}-Kommando gesendet.
\end{longtable} \end{longtable}

View File

@ -1,15 +0,0 @@
% $Id$
\begin{longtable}{|X l|}
% KILLED & LINE!!!! \kill
\hline
\endfirsthead
\endhead
\endfoot
\hline
\endlastfoot
\multicolumn{2}{|X|}{\texttt{until }\textsl{Bedingung}} \\
\multicolumn{2}{|X|}{\texttt{do}} \\
\multicolumn{2}{|X|}{\texttt{~}\textsl{Befehle}} \\
\multicolumn{2}{|X|}{\texttt{done}} \\
\end{longtable}

View File

@ -1,15 +0,0 @@
% $Id$
\begin{longtable}{|X l|}
% KILLED & LINE!!!! \kill
\hline
\endfirsthead
\endhead
\endfoot
\hline
\endlastfoot
\multicolumn{2}{|X|}{\texttt{while }\textsl{Bedingung}} \\
\multicolumn{2}{|X|}{\texttt{do}} \\
\multicolumn{2}{|X|}{\texttt{~}\textsl{Befehle}} \\
\multicolumn{2}{|X|}{\texttt{done}} \\
\end{longtable}

View File

@ -9,12 +9,12 @@ Nachteile der Shell zum tragen: Die Geschwindigkeit.
In einem Shell-Skript wird für jedes externe Kommando\footnote{Externe In einem Shell-Skript wird für jedes externe Kommando\footnote{Externe
Kommandos sind solche, die nicht direkt in der Shell enthalten sind, für die Kommandos sind solche, die nicht direkt in der Shell enthalten sind, für die
also eine eigene Datei aufgerufen wird.} ein eigener Prozeß gestartet. Das also ein eigenes Binary aufgerufen wird.} ein eigener Prozeß gestartet. Das
kostet natürlich Zeit und Speicher. kostet natürlich Zeit und Speicher.
Zeitkritische Anwendungen sind also kein Einsatzgebiet für Shell-Skripte. Die Zeitkritische Anwendungen sind also kein Einsatzgebiet für Shell-Skripte. Die
schreibt man besser in Perl, oder noch besser in einer `compilierten' Sprache schreibt man besser in Perl, Python, oder noch besser in einer `compilierten'
wie C oder C++. Sprache wie C oder C++.
Es stehen jedoch an der Shell viele sehr nützliche externe Kommandos zur Es stehen jedoch an der Shell viele sehr nützliche externe Kommandos zur
Ver\-\-gung, die einem die Entwicklung entsprechender eigener Routinen Ver\-\-gung, die einem die Entwicklung entsprechender eigener Routinen
@ -64,7 +64,7 @@ nur Dateien im Sinne von `ein paar Kilobytes Daten, die irgendwo auf der
Festplatte rumliegen' gibt. Vielmehr findet man hier die Geräte des Rechners Festplatte rumliegen' gibt. Vielmehr findet man hier die Geräte des Rechners
als Dateien unter /dev. Der Kernel selbst stellt Schnittstellen in Form von als Dateien unter /dev. Der Kernel selbst stellt Schnittstellen in Form von
virtuellen Dateien unter /proc (ab Kernel 2.6 auch unter /sys) zur Verfügung. virtuellen Dateien unter /proc (ab Kernel 2.6 auch unter /sys) zur Verfügung.
Und Schlußendlich können Prozesse sich sogenannte Named Pipes\index{Named Pipe} Und schlußendlich können Prozesse sich sogenannte Named Pipes\index{Named Pipe}
anlegen, in die sie schreiben oder aus denen sie lesen. anlegen, in die sie schreiben oder aus denen sie lesen.
Diese Kommandos sind also universell nützlich, nicht nur im Zusammenhang mit Diese Kommandos sind also universell nützlich, nicht nur im Zusammenhang mit
@ -72,6 +72,7 @@ Dateien auf der Festplatte.
\begin{itemize} \begin{itemize}
\item \texttt{cat} (\ref{cat}): Dateien einlesen und ausgeben \item \texttt{cat} (\ref{cat}): Dateien einlesen und ausgeben
\item \texttt{date} (\ref{date}): Datum oder Zeit ausgeben
\item \texttt{echo} (\ref{echo}): Daten ausgeben \item \texttt{echo} (\ref{echo}): Daten ausgeben
\item \texttt{grep} (\ref{grep}): In Dateien suchen \item \texttt{grep} (\ref{grep}): In Dateien suchen
\item \texttt{head} (\ref{head}): Dateianfang ausgeben \item \texttt{head} (\ref{head}): Dateianfang ausgeben
@ -578,6 +579,39 @@ Dateien in Spalten zusammengef
\index{cut=\texttt{cut}|)} \index{cut=\texttt{cut}|)}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\subsection{date}\label{date}\index{date=\texttt{date}|(textbf}
Ein einfacher Aufruf von \texttt{date} führt zu einem Ergebnis in der Art:
\lstinline|Do Jan 27 00:17:51 CET 2005|
Wie man sieht, wird das Datum auf dem System entsprechend der lokalen
Einstellungen ausgegeben. Auf diesem Rechner ist das deutsch, auf den meisten
Rechnern wird Englisch voreingestellt sein.
Neben dieser umfassenden aber starren Ausgabe ist es möglich, das Datum den
eigenen Wünschen entsprechend zu formatieren. Ein paar Beispiele:
\begin{lstlisting}
$ date +"%d.%m.%y, %H:%M"
27.01.05, 00:17
$ date +"Heute ist %A."
Heute ist Donnerstag.
$ date +"%A ist der %u. Tag der Woche."
Donnerstag ist der 4. Tag der Woche.
\end{lstlisting}
Die zur Formatierung bereitstehenden Platzhalter stehen in der Man-Page.
Eigentlich sollte \texttt{\%s} zur Ausgabe der Unix-Systemzeit
\footnote{Sekunden seit dem 01.01.1970, 0:00 Uhr} ein naheliegender Parameter
sein, leider steht er nur in der GNU-Version von \texttt{date} zur Verfügung.
\index{date=\texttt{date}|)}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\subsection{diff}\label{diff}\index{diff=\texttt{diff}|(textbf} \subsection{diff}\label{diff}\index{diff=\texttt{diff}|(textbf}
@ -638,10 +672,12 @@ ist noch einmal aus. So ist es m
Variablen zu bilden. Variablen zu bilden.
Eine wichtige Anwendung für dieses Kommando ist der Fall, wenn eigentlich ein Eine wichtige Anwendung für dieses Kommando ist der Fall, wenn eigentlich ein
Array\index{Array} gebraucht würde. Der Inhalt eines Array-Elements kann Array\index{Array} gebraucht würde. Wenn \texttt{arr} der Name des Arrays und
beispielsweise mittels \lstinline|eval echo \$arr$index| ausgegeben \texttt{index} der Name der Variablen ist, die den Index des auszugebenden
werden, dabei ist \texttt{arr} der Name des Arrays und \texttt{index} der Name Elementes enthält, dann kann durch die folgende Zeile der Inhalt eines
der Variablen, die den Index des auszugebenden Elementes enthält. Array-Elementes ausgegeben werden:
\lstinline|eval echo \$arr$index|
\index{eval=\texttt{eval}|)} \index{eval=\texttt{eval}|)}
@ -820,12 +856,12 @@ ein Skript auf Signale reagieren kann.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\subsection{killall}\label{killall}\index{killall=\texttt{killall}|(textbf}\marginpar{GNU!} \subsection{killall}\label{killall}\index{killall=\texttt{killall}|(textbf}
Im Abschnitt über \texttt{kill} (\ref{kill}) wird beschrieben, wie man ein Im Abschnitt über \texttt{kill} (\ref{kill}) wird beschrieben, wie man ein
Signal an einen Prozeß schickt, dessen ID bekannt ist. Kennt man die ID nicht, Signal an einen Prozeß schickt, dessen ID bekannt ist. Kennt man die ID nicht,
oder will man das Signal an mehrere Prozesse schicken, kann dieses Kommando auf oder will man das Signal an mehrere Prozesse schicken, kann dieses Kommando auf
GNU-Systemen eine große Hilfe darstellen. vielen Systemen eine große Hilfe darstellen.
Mit dem Parameter \texttt{-i} wird vor jedem Signal interaktiv gefragt, ob es Mit dem Parameter \texttt{-i} wird vor jedem Signal interaktiv gefragt, ob es
geschickt werden soll. Mit \texttt{-v} wird angegeben, ob die Signale geschickt werden soll. Mit \texttt{-v} wird angegeben, ob die Signale
@ -1626,7 +1662,7 @@ sich auch nochmal eine ausf
Ein weiterer nützlicher Einsatz für \texttt{trap} ist es, Signale zu Ein weiterer nützlicher Einsatz für \texttt{trap} ist es, Signale zu
ignorieren. Das kann gewünscht sein, wenn eine Folge von Kommandos in einem ignorieren. Das kann gewünscht sein, wenn eine Folge von Kommandos in einem
Skript auf keinen Fall unterbrochen werden darf. Um zu verhindern daß ein Skript auf keinen Fall unterbrochen werden darf. Um zu verhindern daß ein
\Ovalbox{CTRL}-\Ovalbox{C} des Benutzers das Skript beendet wird folgendes \Ovalbox{CTRL}+\Ovalbox{C} des Benutzers das Skript beendet wird folgendes
Konstrukt eingesetzt: Konstrukt eingesetzt:
\begin{lstlisting} \begin{lstlisting}
@ -1737,14 +1773,18 @@ unterscheidet sich von System zu System}.
Ein weiterer und in der Praxis mindestens ebenso sinnvoller Einsatzzweck ist Ein weiterer und in der Praxis mindestens ebenso sinnvoller Einsatzzweck ist
das Vermeiden von Schleifen. Das obige Problem ließe sich auch mit einer Zeile das Vermeiden von Schleifen. Das obige Problem ließe sich auch mit einer Zeile
in der Form \lstinline|find / -name \*.txt -exec grep 'text' {} \;| lösen. in der folgende Form lösen:
Allerdings hätte das den Nachteil, daß für jede gefundene Datei ein neuer
\texttt{grep} gestartet werden muß. Das kostet Resourcen.
Beide Probleme werden durch eine Zeile in der Form \lstinline|find / -name \*.txt -exec grep 'text' {} \;|
\lstinline+find / -name \*.txt | xargs grep 'text'+ umgangen. Dabei liest
\texttt{xargs} aus der Standardeingabe die Parameter, die dann an den Allerdings hätte das den Nachteil, daß für jede gefundene Datei ein neuer
\texttt{grep}-Aufruf angehängt werden. Sollten zu viele Dateien gefunden \texttt{grep} gestartet werden muß. Das kostet Resourcen. Beide Probleme werden
durch eine Zeile in der folgenden Form umgangen:
\lstinline+find / -name \*.txt | xargs grep 'text'+
Dabei liest \texttt{xargs} aus der Standardeingabe die Parameter, die dann an
den \texttt{grep}-Aufruf angehängt werden. Sollten zu viele Dateien gefunden
werden, wird \texttt{grep} mehrfach aufgerufen, allerdings im Gegensatz zum werden, wird \texttt{grep} mehrfach aufgerufen, allerdings im Gegensatz zum
obigen Beispiel nicht einmal pro Fundstelle. obigen Beispiel nicht einmal pro Fundstelle.

View File

@ -82,9 +82,9 @@ einfach durch \lstinline|./skriptname| sondern durch
\lstinline|sh -x ./skriptname|. \lstinline|sh -x ./skriptname|.
\item \texttt{set -v}: Dies funktioniert genau wie \lstinline|set -x|, auch der \item \texttt{set -v}: Dies funktioniert genau wie \lstinline|set -x|, auch der
Aufruf über \lstinline|sh -v ./skriptname| funktioniert. Diese Option gibt jede Aufruf von der Kommandozeile über \lstinline|sh -v ./skriptname| funktioniert.
Zeile vor der Ausführung aus, allerdings im Gegensatz zu \texttt{-x} nicht in Diese Option gibt jede Zeile vor der Ausführung aus, allerdings im Gegensatz zu
der expandierten sondern in der vollen Form. \texttt{-x} nicht in der expandierten sondern in der vollen Form.
\item \texttt{set -e}: Alle gängigen Shell-Kommandos liefern einen \item \texttt{set -e}: Alle gängigen Shell-Kommandos liefern einen
Rückgabewert, der Auskunft über Erfolg oder Mißerfolg gibt (siehe Abschnitt Rückgabewert, der Auskunft über Erfolg oder Mißerfolg gibt (siehe Abschnitt
@ -152,13 +152,22 @@ der Variable \texttt{\$?}\index{\$?=\texttt{\$?}} abgelegt.
Programme den Wert 0 zurück, bei irgendwelchen Problemen einen von 0 Programme den Wert 0 zurück, bei irgendwelchen Problemen einen von 0
verschiedenen Wert. Das wird im folgenden Beispiel deutlich: verschiedenen Wert. Das wird im folgenden Beispiel deutlich:
\LTXtable{\textwidth}{tab_beisp_exitcode.tex} \begin{lstlisting}
$ cp datei /tmp
$ echo $?
0
$ cp datie /tmp
cp: datie: Datei oder Verzeichnis nicht gefunden
$ echo $?
1
\end{lstlisting}
Normalerweise wird man den Exit-Code nicht in dieser Form abfragen. Sinnvoller Normalerweise wird man den Exit-Code nicht in dieser Form abfragen. Sinnvoller
ist folgendes Beispiel, in dem eine Datei erst gedruckt wird, und dann~--~falls ist folgendes Beispiel, in dem eine Datei erst gedruckt wird, und dann~--~falls
der Ausdruck erfolgreich war~--~gelöscht wird: der Ausdruck erfolgreich war~--~gelöscht wird:
\LTXtable{\textwidth}{tab_beisp_exitcode_lpr.tex} \lstinline/$ lpr datei && rm datei/\index{\&\&=\texttt{\&\&}}
Näheres zur Verknüpfung von Aufrufen steht im Kapitel über Befehlsformen Näheres zur Verknüpfung von Aufrufen steht im Kapitel über Befehlsformen
(\ref{befehlsformen}). Beispiele zur Benutzung von Rückgabewerten in Schleifen (\ref{befehlsformen}). Beispiele zur Benutzung von Rückgabewerten in Schleifen
@ -303,7 +312,22 @@ Die folgenden Zeichen k
\LTXtable{\textwidth}{tab_quoting_zeichen.tex} \LTXtable{\textwidth}{tab_quoting_zeichen.tex}
\medskip\emph{Beispiele:}\nopagebreak \medskip\emph{Beispiele:}\nopagebreak
\LTXtable{\textwidth}{tab_beisp_quoting.tex}
\begin{lstlisting}
$ echo 'Ticks "schützen" Anführungszeichen'
Ticks "schützen" Anführungszeichen
$ echo "Ist dies ein \"Sonderfall\"?"
Ist dies ein "Sonderfall"?
$ echo "Sie haben `ls | wc -l` Dateien in `pwd`"
Sie haben 43 Dateien in /home/rschaten
$ echo "Der Wert von \$x ist $x"
Der Wert von $x ist 100
\end{lstlisting}
\index{Anführungszeichen|)}\index{Ticks|)}\index{Backslash|)}\index{;=\texttt{;}|)}\index{\&=\texttt{\&}|)}\index{( )=\texttt{( )}|)}\index{|=\texttt{|}|)}\index{<=\texttt{<}|)}\index{!>=\texttt{!>}|)}\index{!>\&=\texttt{!>\&}|)}\index{*=\texttt{*}|)}\index{?=\texttt{?}|)}\index{[ ]=\texttt{[ ]}|)}\index{\~{}=\texttt{\~{}}|)}\index{+=\texttt{+}|)}\index{-=\texttt{-}|)}\index{@=\texttt{@}|)}\index{!!=\texttt{!!}|)}\index{Backticks|)}\index{\$=\texttt{\$}|)}\index{[newline]=\texttt{[newline]}|)}\index{[space]=\texttt{[space]}|)}\index{[tab]=\texttt{[tab]}|)} \index{Anführungszeichen|)}\index{Ticks|)}\index{Backslash|)}\index{;=\texttt{;}|)}\index{\&=\texttt{\&}|)}\index{( )=\texttt{( )}|)}\index{|=\texttt{|}|)}\index{<=\texttt{<}|)}\index{!>=\texttt{!>}|)}\index{!>\&=\texttt{!>\&}|)}\index{*=\texttt{*}|)}\index{?=\texttt{?}|)}\index{[ ]=\texttt{[ ]}|)}\index{\~{}=\texttt{\~{}}|)}\index{+=\texttt{+}|)}\index{-=\texttt{-}|)}\index{@=\texttt{@}|)}\index{!!=\texttt{!!}|)}\index{Backticks|)}\index{\$=\texttt{\$}|)}\index{[newline]=\texttt{[newline]}|)}\index{[space]=\texttt{[space]}|)}\index{[tab]=\texttt{[tab]}|)}
\index{Quoting|)} \index{Quoting|)}
@ -326,7 +350,18 @@ Die wichtigsten Meta-Zeichen sind:\nopagebreak
werden nicht von jeder Shell unterstützt. werden nicht von jeder Shell unterstützt.
\medskip\emph{Beispiele:}\nopagebreak \medskip\emph{Beispiele:}\nopagebreak
\LTXtable{\textwidth}{tab_beisp_metazeichen.tex}
\begin{lstlisting}
# Alle Dateien listen, die mit 'neu' anfangen:
$ ls neu*
# 'neuX', 'neu4', aber nicht 'neu10' listen:
$ ls neu?
# Alle Dateien listen, die mit einem Grossbuchstaben zwischen D und R
# anfangen - Natuerlich ist die Shell auch hier Case-Sensitive:
$ ls [D-R]*
\end{lstlisting}
Hier ist anzumerken, daß Hidden Files (Dateien, deren Name mit einem Punkt Hier ist anzumerken, daß Hidden Files (Dateien, deren Name mit einem Punkt
beginnt) nicht durch ein einfaches \texttt{*} erfaßt werden, sondern nur durch beginnt) nicht durch ein einfaches \texttt{*} erfaßt werden, sondern nur durch
@ -410,7 +445,22 @@ expandierten Text erhalten. So lassen sich auch Variablen durch diese Technik
erzeugen. erzeugen.
\medskip\emph{Beispiele:}\nopagebreak \medskip\emph{Beispiele:}\nopagebreak
\LTXtable{\textwidth}{tab_beisp_klammerexpansion.tex} \begin{lstlisting}
# Folgende Verzeichnisse erzeugen:
# - /usr/local/src/bash/old
# - /usr/local/src/bash/new
# - /usr/local/src/bash/dist
# - /usr/local/src/bash/bugs
$ mkdir /usr/local/src/bash/{old,new,dist,bugs}
# Die folgenden Dateien / Verzeichnisse dem Benutzer root zuweisen:
# - /usr/ucb/ex
# - /usr/ucb/edit
# - /usr/lib/ex?.?*
# - /usr/lib/how_ex
# Dabei wird /usr/lib/ex?.?* noch weiter expandiert.
$ chown root /usr/{ucb/{ex,edit},lib/{ex?.?*,how_ex}}
\end{lstlisting}
\index{Klammer-Expansion|)} \index{Klammer-Expansion|)}
@ -515,7 +565,11 @@ der Bourne-Shell wirkt das f
\subsection{Null-Befehl (\texttt{:})}\label{null-befehl}\index{Null-Befehl|(textbf}\index{:=\texttt{:}|see{Null-Befehl}}\index{Doppelpunkt|see{Null-Befehl}} \subsection{Null-Befehl (\texttt{:})}\label{null-befehl}\index{Null-Befehl|(textbf}\index{:=\texttt{:}|see{Null-Befehl}}\index{Doppelpunkt|see{Null-Befehl}}
Dieser Befehl tut nichts, außer den Status 0 zurückzugeben. Er wird benutzt, um Endlosschleifen\index{Endlosschleife} zu schreiben (siehe unter \ref{while}), oder um leere Blöcke in \texttt{if}- oder \texttt{case}-Konstrukten\index{if=\texttt{if}}\index{case=\texttt{case}} möglich zu machen. Dieser Befehl tut nichts, außer den Status 0 zurückzugeben. Er wird benutzt, um
Endlosschleifen\index{Endlosschleife} zu schreiben (siehe unter \ref{while}),
oder um leere Blöcke in \texttt{if}- oder
\texttt{case}-Konstrukten\index{if=\texttt{if}}\index{case=\texttt{case}}
möglich zu machen.
\begin{lstlisting} \begin{lstlisting}
if who | grep $1 > /dev/null; then # who: Liste der Benutzer if who | grep $1 > /dev/null; then # who: Liste der Benutzer
@ -561,7 +615,13 @@ Funktion aufgerufenen Kommandos, es sei denn man gibt mittels
Verzeichnis aus. Aufgerufen wird diese Funktion wie ein Befehl, also einfach Verzeichnis aus. Aufgerufen wird diese Funktion wie ein Befehl, also einfach
durch die Eingabe von \texttt{count}. durch die Eingabe von \texttt{count}.
\LTXtable{\textwidth}{tab_beisp_funktionen.tex} \begin{lstlisting}
count () {
ls -1 | wc -l # ls: Liste aller Dateien im Verzeichnis
# Mit Parameter -1 einspaltig
# wc: Word-Count, zählt mit Parameter -l Zeilen
}
\end{lstlisting}
\index{Funktion|)} \index{Funktion|)}
@ -604,17 +664,50 @@ Bedingungen k
\subsection{if\ldots}\label{if}\index{if=\texttt{if}|(textbf}\index{then=\texttt{then}|see{if}}\index{elif=\texttt{elif}|see{if}}\index{else=\texttt{else}|see{if}}\index{fi=\texttt{fi}|see{if}} \subsection{if\ldots}\label{if}\index{if=\texttt{if}|(textbf}\index{then=\texttt{then}|see{if}}\index{elif=\texttt{elif}|see{if}}\index{else=\texttt{else}|see{if}}\index{fi=\texttt{fi}|see{if}}
Die \texttt{if}-Anweisung in der Shell-Programmierung macht das gleiche wie in allen anderen Programmiersprachen, sie testet eine Bedingung auf Wahrheit und macht davon den weiteren Ablauf des Programms abhängig. Die \texttt{if}-Anweisung in der Shell-Programmierung macht das gleiche wie in
allen anderen Programmiersprachen, sie testet eine Bedingung auf Wahrheit und
macht davon den weiteren Ablauf des Programms abhängig.
Die Syntax der \texttt{if}-Anweisung lautet wie folgt:\nopagebreak Die Syntax der \texttt{if}-Anweisung lautet wie folgt:\nopagebreak
\LTXtable{\textwidth}{tab_if.tex}
Wenn die \textsl{Bedingung1} erfüllt ist, werden die \textsl{Befehle1} ausgeführt; andernfalls, wenn die \textsl{Bedingung2} erfüllt ist, werden die \textsl{Befehle2} ausgeführt. Trifft keine Bedingung zu, sollen die \textsl{Befehle3} ausgeführt werden. \begin{sybox}
\texttt{if }\textsl{Bedingung1} \\
\texttt{then }\textsl{Befehle1} \\
\textsl{[}\texttt{ elif }\textsl{Bedingung2} \\
\hspace*{1em}\texttt{then }\textsl{Befehle2 ]} \\
\hspace*{1em}\texttt{\vdots} \\
\textsl{[}\texttt{ else }\textsl{Befehle3 ]} \\
\texttt{fi}
\end{sybox}
Bedingungen werden normalerweise mit dem Befehl \texttt{test}\index{test=\texttt{test}} (siehe unter \ref{bedingungen}) formuliert. Es kann aber auch der Rückgabewert\footnote{Siehe unter \ref{exitcode}.}\index{Rückgabewert} jedes anderen Kommandos ausgewertet werden. Für Bedingungen, die auf jeden Fall zutreffen sollen steht der Null-Befehl (\texttt{:}, siehe unter \ref{null-befehl}) zur Verfügung. Wenn die \textsl{Bedingung1} erfüllt ist, werden die \textsl{Befehle1}
ausgeführt; andernfalls, wenn die \textsl{Bedingung2} erfüllt ist, werden die
\textsl{Befehle2} ausgeführt. Trifft keine Bedingung zu, sollen die
\textsl{Befehle3} ausgeführt werden.
Bedingungen werden normalerweise mit dem Befehl
\texttt{test}\index{test=\texttt{test}} (siehe unter \ref{bedingungen})
formuliert. Es kann aber auch der Rückgabewert\footnote{Siehe unter
\ref{exitcode}.}\index{Rückgabewert} jedes anderen Kommandos ausgewertet
werden. Für Bedingungen, die auf jeden Fall zutreffen sollen steht der
Null-Befehl (\texttt{:}, siehe unter \ref{null-befehl}) zur Verfügung.
\medskip\emph{Beispiele:} Man achte auf die Positionierung der Semikola\footnote{Und man verzeihe mir einen eventuell falschen Plural\ldots :-)}.\nopagebreak \medskip\emph{Beispiele:} Man achte auf die Positionierung der Semikola\footnote{Und man verzeihe mir einen eventuell falschen Plural\ldots :-)}.\nopagebreak
\LTXtable{\textwidth}{tab_beisp_if.tex}
\begin{lstlisting}
# Fuege eine 0 vor Zahlen kleiner 10 ein:
if [ $counter -lt 10 ]; then
number=0$counter
else
number=$counter;
fi
# Loesche ein Verzeichnis, wenn es existiert:
if [ -d $dir ]; then
rmdir $dir # rmdir: Verzeichnis loeschen
fi
\end{lstlisting}
\index{if=\texttt{if}|)} \index{if=\texttt{if}|)}
@ -624,14 +717,54 @@ Bedingungen werden normalerweise mit dem Befehl \texttt{test}\index{test=\texttt
Auch die \texttt{case}-Anweisung ist vergleichbar in vielen anderen Sprachen vorhanden. Sie dient, ähnlich wie die \texttt{if}-Anweisung zur Fallunterscheidung\index{Fallunterscheidung|see{case}}\index{Fallunterscheidung|see{if}}. Allerdings wird hier nicht nur zwischen zwei Fällen unterschieden (Entweder / Oder), sondern es sind mehrere Fälle möglich. Man kann die \texttt{case}-Anweisung auch durch eine geschachtelte \texttt{if}-Anweisung völlig umgehen, allerdings ist sie ein elegantes Mittel um den Code lesbar zu halten. Auch die \texttt{case}-Anweisung ist vergleichbar in vielen anderen Sprachen vorhanden. Sie dient, ähnlich wie die \texttt{if}-Anweisung zur Fallunterscheidung\index{Fallunterscheidung|see{case}}\index{Fallunterscheidung|see{if}}. Allerdings wird hier nicht nur zwischen zwei Fällen unterschieden (Entweder / Oder), sondern es sind mehrere Fälle möglich. Man kann die \texttt{case}-Anweisung auch durch eine geschachtelte \texttt{if}-Anweisung völlig umgehen, allerdings ist sie ein elegantes Mittel um den Code lesbar zu halten.
Die Syntax der \texttt{case}-Anweisung lautet wie folgt:\nopagebreak Die Syntax der \texttt{case}-Anweisung lautet wie folgt:\nopagebreak
\LTXtable{\textwidth}{tab_case.tex}
Wenn der \textsl{Wert} mit dem \textsl{Muster1} übereinstimmt, wird die entsprechende Befehlsfolge\index{Befehls>-folge} (\textsl{Befehle1}) ausgeführt, bei Übereinstimmung mit \textsl{Muster2} werden die Kommandos der zweiten Befehlsfolge\index{Befehls>-folge} (\textsl{Befehle2}) ausgeführt, usw. Der letzte Befehl in jeder Gruppe muß mit \texttt{;;} gekennzeichnet werden. Das bedeutet für die Shell soviel wie `springe zum nächsten \texttt{esac}', so daß die anderen Bedingungen nicht mehr überprüft werden. \begin{sybox}
\texttt{case }\textsl{Wert}\texttt{ in} \\
\hspace*{1em}\textsl{Muster1}\texttt{) }\textsl{Befehle1}\texttt{;;} \\
\hspace*{1em}\textsl{Muster2}\texttt{) }\textsl{Befehle2}\texttt{;;} \\
\hspace*{1em}\texttt{\vdots} \\
\texttt{esac} \\
\end{sybox}
In den Mustern sind die gleichen Meta-Zeichen\index{Meta-Zeichen} erlaubt wie bei der Auswahl von Dateinamen. Das bedeutet, daß man durch ein einfaches \texttt{*}\index{*=\texttt{*}} den Default-Pfad kennzeichnen kann. Dieser wird dann durchlaufen, wenn kein anderes Muster zutrifft. Wenn in einer Zeile mehrere Muster angegeben werden sollen, müssen sie durch ein Pipezeichen (\texttt{|}, logisches ODER) getrennt werden. Wenn der \textsl{Wert} mit dem \textsl{Muster1} übereinstimmt, wird die
entsprechende Befehlsfolge\index{Befehls>-folge} (\textsl{Befehle1})
ausgeführt, bei Übereinstimmung mit \textsl{Muster2} werden die Kommandos der
zweiten Befehlsfolge\index{Befehls>-folge} (\textsl{Befehle2}) ausgeführt, usw.
Der letzte Befehl in jeder Gruppe muß mit \texttt{;;} gekennzeichnet werden.
Das bedeutet für die Shell soviel wie `springe zum nächsten \texttt{esac}', so
daß die anderen Bedingungen nicht mehr überprüft werden.
In den Mustern sind die gleichen Meta-Zeichen\index{Meta-Zeichen} erlaubt wie
bei der Auswahl von Dateinamen. Das bedeutet, daß man durch ein einfaches
\texttt{*}\index{*=\texttt{*}} den Default-Pfad kennzeichnen kann. Dieser wird
dann durchlaufen, wenn kein anderes Muster zutrifft. Wenn in einer Zeile
mehrere Muster angegeben werden sollen, müssen sie durch ein Pipezeichen
(\texttt{|}, logisches ODER) getrennt werden.
\medskip\emph{Beispiele:}\nopagebreak \medskip\emph{Beispiele:}\nopagebreak
\LTXtable{\textwidth}{tab_beisp_case.tex}
\begin{lstlisting}
# Mit dem ersten Argument in der Befehlszeile wird die entsprechende
# Aktion festgelegt:
case $1 in # nimmt das erste Argument
Ja|Nein) response=1;;
-[tT]) table=TRUE;;
*) echo "Unbekannte Option"; exit 1;;
esac
# Lies die Zeilen von der Standard-Eingabe, bis eine Zeile mit einem
# einzelnen Punkt eingegeben wird:
while :; do # Null-Befehl (immer wahr)
echo "Zum Beenden . eingeben ==> \c"
read line # read: Zeile von StdIn einlesen
case "$line" in
.) echo "Ausgefuehrt"
break;;
*) echo "$line";;
esac
done
\end{lstlisting}
\index{case=\texttt{case}|)} \index{case=\texttt{case}|)}
@ -648,7 +781,13 @@ trotzdem eine Laufvariable\index{Laufvariable} braucht, mu
\ref{while}).}. \ref{while}).}.
Die Syntax der \texttt{for}-Schleife lautet wie folgt:\nopagebreak Die Syntax der \texttt{for}-Schleife lautet wie folgt:\nopagebreak
\LTXtable{\textwidth}{tab_for.tex}
\begin{sybox}
\texttt{for }\textsl{x [}\texttt{ in }\textsl{Liste ]} \\
\texttt{do} \\
\hspace*{1em}\textsl{Befehle} \\
\texttt{done}
\end{sybox}
Die \textsl{Befehle} werden ausgeführt, wobei der Variablen \textsl{x} Die \textsl{Befehle} werden ausgeführt, wobei der Variablen \textsl{x}
nacheinander die Werte aus der \textsl{Liste} zugewiesen werden. Wie man sieht nacheinander die Werte aus der \textsl{Liste} zugewiesen werden. Wie man sieht
@ -661,21 +800,67 @@ Kommandos \texttt{continue}\index{continue=\texttt{continue}} (\ref{continue})
bzw. \texttt{break}\index{break=\texttt{break}} (\ref{break}) benutzt werden. bzw. \texttt{break}\index{break=\texttt{break}} (\ref{break}) benutzt werden.
\medskip\emph{Beispiele:}\nopagebreak \medskip\emph{Beispiele:}\nopagebreak
\LTXtable{\textwidth}{tab_beisp_for.tex}
\begin{lstlisting}
# Seitenweises Formatieren der Dateien, die auf der Befehlszeile
# angegeben wurden, und speichern des jeweiligen Ergebnisses:
for file do
pr $file > $file.tmp # pr: Formatiert Textdateien
done
# Durchsuche Kapitel zur Erstellung einer Wortliste (wie fgrep -f):
for item in `cat program_list` # cat: Datei ausgeben
do
echo "Pruefung der Kapitel auf"
echo "Referenzen zum Programm $item ..."
grep -c "$item.[co]" chap* # grep: nach Muster suchen
done
# Ermittle einen Ein-Wort-Titel aus jeder Datei und verwende ihn
# als neuen Dateinamen:
for file do
name=`sed -n 's/NAME: //p' $file`
# sed: Skriptsprache zur Textformatierung
mv $file $name # mv: Datei verschieben bzw. umbenennen
done
\end{lstlisting}
\index{for=\texttt{for}|)} \index{for=\texttt{for}|)}
\subsection{while\ldots}\label{while}\index{while=\texttt{while}|(textbf}\index{Schleife>while-=\texttt{while}-|see{while}} \subsection{while\ldots}\label{while}\index{while=\texttt{while}|(textbf}\index{Schleife>while-=\texttt{while}-|see{while}}
Die \texttt{while}-Schleife ist wieder ein Konstrukt, das einem aus vielen anderen Sprachen bekannt ist: die Kopfgesteuerte Schleife. Die \texttt{while}-Schleife ist wieder ein Konstrukt, das einem aus vielen
anderen Sprachen bekannt ist: die Kopfgesteuerte Schleife.
Die Syntax der \texttt{while}-Schleife lautet wie folgt:\nopagebreak Die Syntax der \texttt{while}-Schleife lautet wie folgt:\nopagebreak
\LTXtable{\textwidth}{tab_while.tex}
Die \textsl{Befehle} werden so lange ausgeführt, wie die \textsl{Bedingung} erfüllt ist. Dabei wird die \textsl{Bedingung} vor der Ausführung der \textsl{Befehle} überprüft. Die \textsl{Bedingung} wird dabei üblicherweise, genau wie bei der \texttt{if}-Anweisung, mit mit dem Befehl \texttt{test}\index{test=\texttt{test}} (siehe unter \ref{bedingungen}) formuliert. Wenn die Ausführung eines Schleifendurchlaufs bzw der ganzen Schleife abgebrochen werden soll, müssen die Kommandos \texttt{continue}\index{continue=\texttt{continue}} (\ref{continue}) bzw. \texttt{break}\index{break=\texttt{break}} (\ref{break}) benutzt werden. \begin{sybox}
\texttt{while }\textsl{Bedingung}\texttt{; do} \\
\hspace*{1em}\textsl{Befehle} \\
\texttt{done}
\end{sybox}
Die \textsl{Befehle} werden so lange ausgeführt, wie die \textsl{Bedingung}
erfüllt ist. Dabei wird die \textsl{Bedingung} vor der Ausführung der
\textsl{Befehle} überprüft. Die \textsl{Bedingung} wird dabei üblicherweise,
genau wie bei der \texttt{if}-Anweisung, mit mit dem Befehl
\texttt{test}\index{test=\texttt{test}} (siehe unter \ref{bedingungen})
formuliert. Wenn die Ausführung eines Schleifendurchlaufs bzw der ganzen
Schleife abgebrochen werden soll, müssen die Kommandos
\texttt{continue}\index{continue=\texttt{continue}} (\ref{continue}) bzw.
\texttt{break}\index{break=\texttt{break}} (\ref{break}) benutzt werden.
\medskip\emph{Beispiel:}\nopagebreak \medskip\emph{Beispiel:}\nopagebreak
\LTXtable{\textwidth}{tab_beisp_while.tex}
\begin{lstlisting}
# Zeilenweise Ausgabe aller Aufrufparameter:
while [ -n "$1" ]; do
echo $1
shift # mit shift werden die Parameter nach
# Links geshiftet (aus $2 wird $1)
done
\end{lstlisting}
Eine Standard-Anwendung der \texttt{while}-Schleife ist der Ersatz für die Eine Standard-Anwendung der \texttt{while}-Schleife ist der Ersatz für die
Zählschleife\index{Zählschleife}\index{Schleife>Zähl-=Zähl-|see{Zählschleife}}. Zählschleife\index{Zählschleife}\index{Schleife>Zähl-=Zähl-|see{Zählschleife}}.
@ -688,7 +873,15 @@ das Kommando \texttt{seq} (Siehe Abschnitt \ref{seq}) zur Verf
man die Funktion durch geschickte Anwendung der man die Funktion durch geschickte Anwendung der
\texttt{while}-Schleife:\nopagebreak \texttt{while}-Schleife:\nopagebreak
\LTXtable{\textwidth}{tab_beisp_while_for.tex} \begin{lstlisting}
# Ausgabe der Zahlen von 1 bis 100:
i=1
while [ $i -le 100 ]; do
echo $i
i=`expr $i + 1`
done
\end{lstlisting}
\index{while=\texttt{while}|)} \index{while=\texttt{while}|)}
@ -702,7 +895,12 @@ Es ist also auch eine kopfgesteuerte Schleife, die allerdings so lange l
wie die angegebene Bedingung nicht zutrifft. wie die angegebene Bedingung nicht zutrifft.
Die Syntax der \texttt{until}-Schleife lautet wie folgt:\nopagebreak Die Syntax der \texttt{until}-Schleife lautet wie folgt:\nopagebreak
\LTXtable{\textwidth}{tab_until.tex}
\begin{sybox}
\texttt{until }\textsl{Bedingung}\texttt{; do} \\
\hspace*{1em}\textsl{Befehle} \\
\texttt{done}
\end{sybox}
Die \textsl{Bedingung} wird dabei üblicherweise, genau wie bei der Die \textsl{Bedingung} wird dabei üblicherweise, genau wie bei der
\texttt{if}-Anweisung, mit mit dem Befehl \texttt{if}-Anweisung, mit mit dem Befehl
@ -712,33 +910,61 @@ Schleife abgebrochen werden soll, m
\texttt{continue}\index{continue=\texttt{continue}} (\ref{continue}) bzw. \texttt{continue}\index{continue=\texttt{continue}} (\ref{continue}) bzw.
\texttt{break}\index{break=\texttt{break}} (\ref{break}) benutzt werden. \texttt{break}\index{break=\texttt{break}} (\ref{break}) benutzt werden.
\medskip\emph{Beispiel:} Hier wird die Bedingung nicht per \texttt{test} sondern mit dem Rückgabewert\index{Rückgabewert} des Programms \texttt{grep}\index{grep=\texttt{grep}} formuliert.\nopagebreak \medskip\emph{Beispiel:} Hier wird die Bedingung nicht per \texttt{test}
\LTXtable{\textwidth}{tab_beisp_until.tex} sondern mit dem Rückgabewert\index{Rückgabewert} des Programms
\texttt{grep}\index{grep=\texttt{grep}} formuliert.\nopagebreak
\begin{lstlisting}
# Warten, bis sich der Administrator einloggt:
until who | grep "root"; do
# who: Liste der Benutzer
# grep: Suchen nach Muster
sleep 2 # sleep: warten
done
echo "Der Meister ist anwesend"
\end{lstlisting}
\index{until=\texttt{until}|)} \index{until=\texttt{until}|)}
\subsection{continue}\label{continue}\index{continue=\texttt{continue}|(textbf} \subsection{continue}\label{continue}\index{continue=\texttt{continue}|(textbf}
Die Syntax der \texttt{continue}-Anweisung lautet wie folgt:\nopagebreak Die Syntax der \texttt{continue}-Anweisung lautet wie folgt:\nopagebreak
\LTXtable{\textwidth}{tab_continue.tex}
Man benutzt \texttt{continue} um die restlichen Befehle in einer Schleife zu überspringen und mit dem nächsten Schleifendurchlauf anzufangen. Wenn der Parameter \textsl{n} angegeben wird, werden \textsl{n} Schleifenebenen übersprungen. \begin{sybox}
\texttt{continue }\textsl{[ n ]}
\end{sybox}
Man benutzt \texttt{continue} um die restlichen Befehle in einer Schleife zu
überspringen und mit dem nächsten Schleifendurchlauf anzufangen. Wenn der
Parameter \textsl{n} angegeben wird, werden \textsl{n} Schleifenebenen
übersprungen.
\index{continue=\texttt{continue}|)} \index{continue=\texttt{continue}|)}
\subsection{break}\label{break}\index{break=\texttt{break}|(textbf} \subsection{break}\label{break}\index{break=\texttt{break}|(textbf}
Die Syntax der \texttt{break}-Anweisung lautet wie folgt:\nopagebreak Die Syntax der \texttt{break}-Anweisung lautet wie folgt:\nopagebreak
\LTXtable{\textwidth}{tab_break.tex}
Mit \texttt{break} kann man die innerste Ebene (bzw. \textsl{n} Schleifenebenen) verlassen ohne den Rest der Schleife auszuführen. \begin{sybox}
\texttt{break }\textsl{[ n ]}
\end{sybox}
Mit \texttt{break} kann man die innerste Ebene (bzw. \textsl{n}
Schleifenebenen) verlassen ohne den Rest der Schleife auszuführen.
\index{break=\texttt{break}|)} \index{break=\texttt{break}|)}
\subsection{exit}\label{exit}\index{exit=\texttt{exit}|(textbf} \subsection{exit}\label{exit}\index{exit=\texttt{exit}|(textbf}
Die Syntax der \texttt{exit}-Anweisung lautet wie folgt:\nopagebreak Die Syntax der \texttt{exit}-Anweisung lautet wie folgt:\nopagebreak
\LTXtable{\textwidth}{tab_exit.tex}
\begin{sybox}
\texttt{exit }\textsl{[ n ]}
\end{sybox}
Die \texttt{exit}-Anweisung wird benutzt, um ein Skript zu beenden. Wenn der Parameter \textsl{n} angegeben wird, wird er von dem Skript als Exit-Code zurückgegeben. Die \texttt{exit}-Anweisung wird benutzt, um ein Skript zu beenden. Wenn der Parameter \textsl{n} angegeben wird, wird er von dem Skript als Exit-Code zurückgegeben.
\index{exit=\texttt{exit}|)} \index{exit=\texttt{exit}|)}
@ -747,7 +973,10 @@ Die \texttt{exit}-Anweisung wird benutzt, um ein Skript zu beenden. Wenn der Par
\subsection{return}\label{return}\index{return=\texttt{return}|(textbf} \subsection{return}\label{return}\index{return=\texttt{return}|(textbf}
Die Syntax der \texttt{return}-Anweisung lautet wie folgt:\nopagebreak Die Syntax der \texttt{return}-Anweisung lautet wie folgt:\nopagebreak
\LTXtable{\textwidth}{tab_return.tex}
\begin{sybox}
\texttt{return }\textsl{[ n ]}
\end{sybox}
Mittels \texttt{return} kann eine Funktion (siehe \ref{funktionen}) einen Mittels \texttt{return} kann eine Funktion (siehe \ref{funktionen}) einen
bestimmten Wert zurückgeben. Anderenfalls wird der Exit-Code des letzten in der bestimmten Wert zurückgeben. Anderenfalls wird der Exit-Code des letzten in der
@ -810,11 +1039,26 @@ Zwischen den Dateideskriptoren und einem Umlenkungssymbol darf kein Leerzeichen
\LTXtable{\textwidth}{tab_beisp_datenstroeme.tex} \LTXtable{\textwidth}{tab_beisp_datenstroeme.tex}
\medskip\emph{Beispiel eines Here-Dokuments:}\nopagebreak \medskip\emph{Beispiel eines Here-Dokuments:}\nopagebreak
\LTXtable{\textwidth}{tab_beisp_datenstroeme_here-dokument.tex}
\begin{lstlisting}
# Ein Here-Dokument: Nach dem << wird ein sogenannter Delimiter
# angegeben. Alle folgenden Zeilen werden an die Standard-Eingabe von
# cat übergeben. Der Text wird durch ein erneutes Vorkommen des
# Delimiters (einzeln und am Zeilenanfang) beendet.
cat << EOF
Dieser Text wird zeilenweise ausgegeben,
bis ein einzelnes EOF kommt.
EOF
\end{lstlisting}
Gerade der Mechanismus mit dem Piping sollte nicht unterschätzt werden. Er dient nicht nur dazu, relativ kleine Texte zwischen Tools hin- und herzureichen. An dem folgenden Beispiel soll die Mächtigkeit dieses kleinen Zeichens gezeigt werden:\nopagebreak Gerade der Mechanismus mit dem Piping sollte nicht unterschätzt werden. Er dient nicht nur dazu, relativ kleine Texte zwischen Tools hin- und herzureichen. An dem folgenden Beispiel soll die Mächtigkeit dieses kleinen Zeichens gezeigt werden:\nopagebreak
Es ist mit den passenden Tools unter Unix möglich, eine ganze Audio-CD mit zwei Befehlen an der Kommandozeile zu duplizieren. Das erste Kommando veranlaßt, daß die TOC (Table Of Contents) der CD in die Datei cd.toc geschrieben wird. Das dauert nur wenige Sekunden. Die Pipe steckt im zweiten Befehl. Hier wird der eigentliche Inhalt der CD mit dem Tool `cdparanoia' ausgelesen. Da kein Dateiname angegeben wird, schreibt cdparanoia die Daten auf seine Standard-Ausgabe. Diese wird von dem Brennprogramm `cdrdao' übernommen und in Verbindung mit der TOC `on the fly' auf die CD geschrieben.\label{cdrdao}\nopagebreak Es ist mit den passenden Tools unter Unix möglich, eine ganze Audio-CD mit zwei Befehlen an der Kommandozeile zu duplizieren. Das erste Kommando veranlaßt, daß die TOC (Table Of Contents) der CD in die Datei cd.toc geschrieben wird. Das dauert nur wenige Sekunden. Die Pipe steckt im zweiten Befehl. Hier wird der eigentliche Inhalt der CD mit dem Tool `cdparanoia' ausgelesen. Da kein Dateiname angegeben wird, schreibt cdparanoia die Daten auf seine Standard-Ausgabe. Diese wird von dem Brennprogramm `cdrdao' übernommen und in Verbindung mit der TOC `on the fly' auf die CD geschrieben.\label{cdrdao}\nopagebreak
\LTXtable{\textwidth}{tab_beisp_datenstroeme_cdparanoia.tex}
\begin{lstlisting}
cdrdao read-toc --datafile - cd.toc
cdparanoia -q -R 1- - | cdrdao write --buffers 64 cd.toc
\end{lstlisting}
\index{<=\texttt{<}|)}\index{!>\&=\texttt{!>\&}|)}\index{!>\&-=\texttt{!>\&-}|)}\index{<\&=\texttt{<\&}|)}\index{<\&-=\texttt{<\&-}|)}\index{!>=\texttt{!>}|)}\index{!>!>=\texttt{!>!>}|)}\index{Pipe|)}\index{Dateideskriptor|)}\index{Standard-Eingabe|)}\index{Standard-Ausgabe|)}\index{Standard-Fehlerausgabe|)}\index{Here-Dokument|)textbf} \index{<=\texttt{<}|)}\index{!>\&=\texttt{!>\&}|)}\index{!>\&-=\texttt{!>\&-}|)}\index{<\&=\texttt{<\&}|)}\index{<\&-=\texttt{<\&-}|)}\index{!>=\texttt{!>}|)}\index{!>!>=\texttt{!>!>}|)}\index{Pipe|)}\index{Dateideskriptor|)}\index{Standard-Eingabe|)}\index{Standard-Ausgabe|)}\index{Standard-Fehlerausgabe|)}\index{Here-Dokument|)textbf}
\index{Datenströme|)} \index{Datenströme|)}

View File

@ -4,9 +4,9 @@
Unter DOS werden Batchdateien oft dazu benutzt, lange Kommandos abzukürzen um Unter DOS werden Batchdateien oft dazu benutzt, lange Kommandos abzukürzen um
die Tipparbeit zu vermindern, oder um sich das Merken von vielen Parametern zu die Tipparbeit zu vermindern, oder um sich das Merken von vielen Parametern zu
ersparen. Diese Aufgabe überläßt man unter Unix am besten den ersparen. Diese Aufgabe überläßt man unter Unix am besten den
Shell-Aliasen\index{Aliase} oder Shell-Funktionen.\bigskip Shell-Aliasen\index{Aliase} oder Shell-Funktionen.
Shell-Skripte können viel mehr als Batchdateien.\bigskip Shell-Skripte können viel mehr als Batchdateien.
Wie der Name schon sagt, sind Batchdateien im Wesentlichen nur ein `Stapel' von Wie der Name schon sagt, sind Batchdateien im Wesentlichen nur ein `Stapel' von
Anweisungen, die nacheinander ausgeführt werden. Es stehen zwar auch einige Anweisungen, die nacheinander ausgeführt werden. Es stehen zwar auch einige
@ -24,8 +24,8 @@ DOS keine M
erste Kommando vollständig ausgeführt, seine Ausgabe in eine temporäre Datei erste Kommando vollständig ausgeführt, seine Ausgabe in eine temporäre Datei
geschrieben und danach als Eingabe für das zweite Kommando benutzt. Daß so ein geschrieben und danach als Eingabe für das zweite Kommando benutzt. Daß so ein
Verhalten unter Umständen schnell zu einer vollen Festplatte führen kann, sieht Verhalten unter Umständen schnell zu einer vollen Festplatte führen kann, sieht
man bei dem Beispiel, in dem eine CD kopiert werden soll (Kapitel \ref{cdrdao}, man bei dem Beispiel in Abschnitt \ref{cdrdao}, in dem eine CD kopiert werden
Seite \pageref{cdrdao}). soll.
Shell-Skripte kann man dagegen eher mit einer `richtigen' Programmiersprache Shell-Skripte kann man dagegen eher mit einer `richtigen' Programmiersprache
vergleichen. Es stehen alle Konstrukte zur Verfügung, die eine vergleichen. Es stehen alle Konstrukte zur Verfügung, die eine