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<EFBFBD>hrungszeichen}\index{grep=\texttt{grep}}\index{Pipe}\index{sleep=\texttt{sleep}}\index{who=\texttt{who}} \index{\^=\texttt{\^}}\index{Anf<EFBFBD>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<64> die M<>use tanzen!" echo "Die Katze ist aus dem Haus, Zeit, da<64> die M<>use tanzen!"
\end{lstlisting} \end{lstlisting}
Die Schleife wird n<>mlich dann so lange ausgef<65>hrt, bis \texttt{grep}\index{grep=\texttt{grep}} einen Fehler (bzw. eine erfolglose Suche) zur<75>ckmeldet. Die Schleife wird n<>mlich dann so lange ausgef<65>hrt, bis
\texttt{grep}\index{grep=\texttt{grep}} einen Fehler (bzw. eine erfolglose
Suche) zur<75>ckmeldet.
\section{Subshell-Schleifen vermeiden}\label{subshellschleifen}
Wir wollen ein Skript schreiben, das die \texttt{/etc/passwd} liest und dabei
z<EFBFBD>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 <20>bergibt. Das \texttt{read}-Kommando in der
Schleife liest die einzelnen Zeilen aus, dann folgt ein Bi<42>chen Auswertung.
Es ist zu beobachten, da<64> bei der Ausgabe in Zeile 7 die Variable
\texttt{\$count} korrekte Werte enth<74>lt. Um so unverst<73>ndlicher ist es, da<64> sie
nach der Vollendung der Schleife wieder den Wert 0 enth<74>lt.
Das liegt daran, da<64> diese Schleife als Teil einer Pipe in einer Subshell
ausgef<EFBFBD>hrt wird. Die Variable \texttt{\$count} steht damit in der Schleife
praktisch nur lokal zur Verf<72>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<65>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<7A> gesandt, das ihn diese Taste wird ein Signal an den entsprechenden Proze<7A> gesandt, das ihn
bittet sich zu beenden. Dieses Signal hei<65>t SIGINT (f<>r SIGnal INTerrupt) und bittet sich zu beenden. Dieses Signal hei<65>t SIGINT (f<>r SIGnal INTerrupt) und
tr<EFBFBD>gt die Nummer 2. Das kann ein kleines Problem darstellen, wenn das Skript tr<EFBFBD>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<75>lliger Reihenfolge abspielt. Damit dieses bestimmten Verzeichnisbaum in zuf<75>lliger Reihenfolge abspielt. Damit dieses
Problem f<>r uns eine Herausforderung darstellt\footnote{Denn schlie<69>lich hat Problem f<>r uns eine Herausforderung darstellt\footnote{Denn schlie<69>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,
<EFBFBD>berall liegen Perl-Skripte und andere Dateien. Gesucht sind alle Dateien, in <EFBFBD>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<65>nschten Ergebnis. Da die Unterverzeichnisse Und wieder f<>hrt es nicht zu dem gew<65>nschten Ergebnis. Da die
nicht die Extension `*.pl' tragen, werden sie nicht ber<65>cksichtigt. F<>r die Unterverzeichnisse nicht die Extension `*.pl' tragen, werden sie nicht
Suche in Unterverzeichnissen ziehen wir \texttt{find} (Siehe Abschnitt ber<EFBFBD>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<6E>rt...). kann ich nur jedem empfehlen - es ist spannender als es sich anh<6E>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<65>ber dem Hier wird die Datei verpackt und versendet. Eine Besonderheit gegen<65>ber dem
vorigen Beispiel bestehtdarin, da<64> das Zielverzeichnis bei Bedarf erstellt vorigen Beispiel besteht darin, da<64> das Zielverzeichnis bei Bedarf erstellt
wird, bevor die Datei dort entpackt wird. Zur Erkl<6B>rung: Die Variable wird, bevor die Datei dort entpackt wird. Zur Erkl<6B>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<69>en. Um es nochmal zu betonen: Diese beiden Methoden sind mit Vorsicht zu genie<69>en.
Bei der ersten f<>hrt jede zus<75>tzliche oder gel<65>schte Zeile zu einer kaputten Bei der ersten f<>hrt jede zus<75>tzliche oder gel<65>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<EFBFBD>schen. Gel<65>scht wird n<>mlich zun<75>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<7A> die Datei noch in irgendeiner Form ge<67>ffnet, kann er weiter
darauf zugreifen. Erst wenn er die Datei schlie<69>t ist sie tats<74>chlich und
unwiederbringlich `weg'.
TODO!!! Speichern in nicht existente Dateien Dieser Effekt der `nicht existenten Dateien' l<><6C>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<EFBFBD>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 <20>bergibt. Das \texttt{read}-Kommando in der
Schleife liest die einzelnen Zeilen aus, dann folgt ein Bi<42>chen Auswertung.
Es ist zu beobachten, da<64> bei der Ausgabe in Zeile 7 die Variable
\texttt{\$count} korrekte Werte enth<74>lt. Um so unverst<73>ndlicher ist es, da<64> sie
nach der Vollendung der Schleife wieder den Wert 0 enth<74>lt.
Das liegt daran, da<64> diese Schleife als Teil einer Pipe in einer Subshell
ausgef<EFBFBD>hrt wird. Die Variable \texttt{\$count} steht damit in der Schleife
praktisch nur lokal zur Verf<72>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<65>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<6F>re Datei geschrieben werden, die Komplexere Informationen k<>nnen in eine tempor<6F>re Datei geschrieben werden, die
danach geparst werden m<><6D>te. Wenn die Informationen in Zeilen der Form danach geparst werden m<><6D>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<73>nde zwischen den Abs<62>tzen, statt halfparskip, % Abst<73>nde zwischen den Abs<62>tzen, statt
% Einr<6E>ckung der ersten Zeile % Einr<6E>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<6D> jedes Dokument beginnen \begin{document} % hiermit mu<6D> 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
%<25>bersicht zu diesem Thema haben wollte. Ich beabsichtige nicht, damit in
%irgendeiner Form Kommerz zu machen. Ich stelle es frei zur Verf<72>gung, in der
%Hoffnung, da<64> andere Leute daraus vielleicht einen Nutzen ziehen k<>nnen.
%\textbf{Aber ich <20>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<64> 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<72>nftige Lizenz einsetzen!\bigskip TODO: Vern<72>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
<EFBFBD>bersicht zu diesem Thema haben wollte. Ich beabsichtige nicht, damit in <EFBFBD>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<64> dieses Dokument~--~oder Teile Nutzen ziehen k<>nnen'} meine ich nicht, da<64> 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 <20>ber jede aufmerksam zu machen. Auch abgesehen davon freue ich mich <20>ber jede
R<EFBFBD>ckmeldung.\bigskip R<EFBFBD>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<EFBFBD>hrungszeichen}} \\
\multicolumn{2}{|X|}{\texttt{~echo \dq Referenzen zum Programm \$item ...\dq}\index{Anf<EFBFBD>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<EFBFBD>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<EFBFBD>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<EFBFBD>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<72>buchstaben\index{Gro<EFBFBD>buchstaben}\footnote{Nat<EFBFBD>rlich wird in Shell-Skripten~--~wie (fast) <20>berall in der Unix-Welt~--~zwischen Gro<72>- 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<63>tzen\dq~Anf<6E>hrungszeichen'}} \\
\multicolumn{2}{|X|}{\texttt{Ticks \dq sch<63>tzen\dq~Anf<6E>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<EFBFBD>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<EFBFBD>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<72>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<72>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<75>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<74>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<74>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<72>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<72>lt sie <EFBFBD>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<EFBFBD>ufig verwendet zur Angabe von Leerzeichen (space) und Zeilenendezeichen, oder H<EFBFBD>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<65>st. \tabularnewline\STRUT 0 & Normal Exit & Wird durch das \texttt{exit}\index{exit=\texttt{exit}}-Kommando ausgel<65>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<7A> gestartet. Das also ein eigenes Binary aufgerufen wird.} ein eigener Proze<7A> gestartet. Das
kostet nat<61>rlich Zeit und Speicher. kostet nat<61>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\-f<EFBFBD>\-gung, die einem die Entwicklung entsprechender eigener Routinen Ver\-f<EFBFBD>\-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<65>te des Rechners Festplatte rumliegen' gibt. Vielmehr findet man hier die Ger<65>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<72>gung. virtuellen Dateien unter /proc (ab Kernel 2.6 auch unter /sys) zur Verf<72>gung.
Und Schlu<EFBFBD>endlich k<>nnen Prozesse sich sogenannte Named Pipes\index{Named Pipe} Und schlu<EFBFBD>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<72>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<74>lt, dann kann durch die folgende Zeile der Inhalt eines
der Variablen, die den Index des auszugebenden Elementes enth<74>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 <20>ber \texttt{kill} (\ref{kill}) wird beschrieben, wie man ein Im Abschnitt <20>ber \texttt{kill} (\ref{kill}) wird beschrieben, wie man ein
Signal an einen Proze<7A> schickt, dessen ID bekannt ist. Kennt man die ID nicht, Signal an einen Proze<7A> 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<72>e Hilfe darstellen. vielen Systemen eine gro<72>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<65>nscht sein, wenn eine Folge von Kommandos in einem ignorieren. Das kann gew<65>nscht sein, wenn eine Folge von Kommandos in einem
Skript auf keinen Fall unterbrochen werden darf. Um zu verhindern da<64> ein Skript auf keinen Fall unterbrochen werden darf. Um zu verhindern da<64> 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<69>e sich auch mit einer Zeile das Vermeiden von Schleifen. Das obige Problem lie<69>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<64> f<>r jede gefundene Datei ein neuer
\texttt{grep} gestartet werden mu<6D>. 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<64> f<>r jede gefundene Datei ein neuer
\texttt{grep}-Aufruf angeh<65>ngt werden. Sollten zu viele Dateien gefunden \texttt{grep} gestartet werden mu<6D>. 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<65>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 <20>ber \lstinline|sh -v ./skriptname| funktioniert. Diese Option gibt jede Aufruf von der Kommandozeile <EFBFBD>ber \lstinline|sh -v ./skriptname| funktioniert.
Zeile vor der Ausf<73>hrung aus, allerdings im Gegensatz zu \texttt{-x} nicht in Diese Option gibt jede Zeile vor der Ausf<73>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<EFBFBD>ckgabewert, der Auskunft <20>ber Erfolg oder Mi<4D>erfolg gibt (siehe Abschnitt R<EFBFBD>ckgabewert, der Auskunft <20>ber Erfolg oder Mi<4D>erfolg gibt (siehe Abschnitt
@ -152,13 +152,22 @@ der Variable \texttt{\$?}\index{\$?=\texttt{\$?}} abgelegt.
Programme den Wert 0 zur<75>ck, bei irgendwelchen Problemen einen von 0 Programme den Wert 0 zur<75>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<65>scht wird: der Ausdruck erfolgreich war~--~gel<65>scht wird:
\LTXtable{\textwidth}{tab_beisp_exitcode_lpr.tex} \lstinline/$ lpr datei && rm datei/\index{\&\&=\texttt{\&\&}}
N<EFBFBD>heres zur Verkn<6B>pfung von Aufrufen steht im Kapitel <20>ber Befehlsformen N<EFBFBD>heres zur Verkn<6B>pfung von Aufrufen steht im Kapitel <20>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<63>tzen" Anf<6E>hrungszeichen'
Ticks "sch<63>tzen" Anf<6E>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<EFBFBD>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<EFBFBD>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<73>tzt. werden nicht von jeder Shell unterst<73>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<64> Hidden Files (Dateien, deren Name mit einem Punkt Hier ist anzumerken, da<64> Hidden Files (Dateien, deren Name mit einem Punkt
beginnt) nicht durch ein einfaches \texttt{*} erfa<66>t werden, sondern nur durch beginnt) nicht durch ein einfaches \texttt{*} erfa<66>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<61>er den Status 0 zur<75>ckzugeben. Er wird benutzt, um Endlosschleifen\index{Endlosschleife} zu schreiben (siehe unter \ref{while}), oder um leere Bl<42>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<61>er den Status 0 zur<75>ckzugeben. Er wird benutzt, um
Endlosschleifen\index{Endlosschleife} zu schreiben (siehe unter \ref{while}),
oder um leere Bl<42>cke in \texttt{if}- oder
\texttt{case}-Konstrukten\index{if=\texttt{if}}\index{case=\texttt{case}}
m<EFBFBD>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<62>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<62>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<72>llt ist, werden die \textsl{Befehle1} ausgef<65>hrt; andernfalls, wenn die \textsl{Bedingung2} erf<72>llt ist, werden die \textsl{Befehle2} ausgef<65>hrt. Trifft keine Bedingung zu, sollen die \textsl{Befehle3} ausgef<65>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<EFBFBD>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<72>gung. Wenn die \textsl{Bedingung1} erf<72>llt ist, werden die \textsl{Befehle1}
ausgef<EFBFBD>hrt; andernfalls, wenn die \textsl{Bedingung2} erf<72>llt ist, werden die
\textsl{Befehle2} ausgef<65>hrt. Trifft keine Bedingung zu, sollen die
\textsl{Befehle3} ausgef<65>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<EFBFBD>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<72>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, <20>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, <20>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} <20>bereinstimmt, wird die entsprechende Befehlsfolge\index{Befehls>-folge} (\textsl{Befehle1}) ausgef<65>hrt, bei <20>bereinstimmung mit \textsl{Muster2} werden die Kommandos der zweiten Befehlsfolge\index{Befehls>-folge} (\textsl{Befehle2}) ausgef<65>hrt, usw. Der letzte Befehl in jeder Gruppe mu<6D> mit \texttt{;;} gekennzeichnet werden. Das bedeutet f<>r die Shell soviel wie `springe zum n<>chsten \texttt{esac}', so da<64> die anderen Bedingungen nicht mehr <20>berpr<70>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<64> 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} <20>bereinstimmt, wird die
entsprechende Befehlsfolge\index{Befehls>-folge} (\textsl{Befehle1})
ausgef<EFBFBD>hrt, bei <20>bereinstimmung mit \textsl{Muster2} werden die Kommandos der
zweiten Befehlsfolge\index{Befehls>-folge} (\textsl{Befehle2}) ausgef<65>hrt, usw.
Der letzte Befehl in jeder Gruppe mu<6D> mit \texttt{;;} gekennzeichnet werden.
Das bedeutet f<>r die Shell soviel wie `springe zum n<>chsten \texttt{esac}', so
da<EFBFBD> die anderen Bedingungen nicht mehr <20>berpr<70>ft werden.
In den Mustern sind die gleichen Meta-Zeichen\index{Meta-Zeichen} erlaubt wie
bei der Auswahl von Dateinamen. Das bedeutet, da<64> 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<65>hrt, wobei der Variablen \textsl{x} Die \textsl{Befehle} werden ausgef<65>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<65>hrt, wie die \textsl{Bedingung} erf<72>llt ist. Dabei wird die \textsl{Bedingung} vor der Ausf<73>hrung der \textsl{Befehle} <20>berpr<70>ft. Die \textsl{Bedingung} wird dabei <20>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<73>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<65>hrt, wie die \textsl{Bedingung}
erf<EFBFBD>llt ist. Dabei wird die \textsl{Bedingung} vor der Ausf<73>hrung der
\textsl{Befehle} <20>berpr<70>ft. Die \textsl{Bedingung} wird dabei <20>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<73>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<EFBFBD>hlschleife\index{Z<EFBFBD>hlschleife}\index{Schleife>Z<>hl-=Z<EFBFBD>hl-|see{Z<EFBFBD>hlschleife}}. Z<EFBFBD>hlschleife\index{Z<EFBFBD>hlschleife}\index{Schleife>Z<>hl-=Z<EFBFBD>hl-|see{Z<EFBFBD>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 <20>blicherweise, genau wie bei der Die \textsl{Bedingung} wird dabei <20>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<EFBFBD>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<EFBFBD>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 <20>berspringen und mit dem n<>chsten Schleifendurchlauf anzufangen. Wenn der Parameter \textsl{n} angegeben wird, werden \textsl{n} Schleifenebenen <20>bersprungen. \begin{sybox}
\texttt{continue }\textsl{[ n ]}
\end{sybox}
Man benutzt \texttt{continue} um die restlichen Befehle in einer Schleife zu
<EFBFBD>berspringen und mit dem n<>chsten Schleifendurchlauf anzufangen. Wenn der
Parameter \textsl{n} angegeben wird, werden \textsl{n} Schleifenebenen
<EFBFBD>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<75>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<75>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<75>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<75>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<75>ckgeben. Anderenfalls wird der Exit-Code des letzten in der bestimmten Wert zur<75>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 <20>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<63>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<63>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<6C>t, da<64> 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' <20>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<6C>t, da<64> 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' <20>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<EFBFBD>me|)} \index{Datenstr<EFBFBD>me|)}

View File

@ -4,9 +4,9 @@
Unter DOS werden Batchdateien oft dazu benutzt, lange Kommandos abzuk<75>rzen um Unter DOS werden Batchdateien oft dazu benutzt, lange Kommandos abzuk<75>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 <20>berl<72><6C>t man unter Unix am besten den ersparen. Diese Aufgabe <20>berl<72><6C>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<65>hrt werden. Es stehen zwar auch einige Anweisungen, die nacheinander ausgef<65>hrt werden. Es stehen zwar auch einige
@ -24,8 +24,8 @@ DOS keine M
erste Kommando vollst<73>ndig ausgef<65>hrt, seine Ausgabe in eine tempor<6F>re Datei erste Kommando vollst<73>ndig ausgef<65>hrt, seine Ausgabe in eine tempor<6F>re Datei
geschrieben und danach als Eingabe f<>r das zweite Kommando benutzt. Da<44> so ein geschrieben und danach als Eingabe f<>r das zweite Kommando benutzt. Da<44> so ein
Verhalten unter Umst<73>nden schnell zu einer vollen Festplatte f<>hren kann, sieht Verhalten unter Umst<73>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<72>gung, die eine vergleichen. Es stehen alle Konstrukte zur Verf<72>gung, die eine