% $Id$ \chapter{Nützliche Shell-Kommandos}\label{nuetzliche_shell-kommandos} Durch die gezeigten Steuerungsmöglichkeiten stehen dem Shell-Pro\-grammie\-rer Mög\-lich\-kei\-ten offen, fast alle gängigen Algorithmen zu implementieren. Es ist tatsächlich in der Shell möglich, Sortier- oder Suchfunktionen zu schreiben. Leider kommt aber an dieser Stelle einer der bedeutendsten Nachteile der Shell zum tragen: Die Geschwindigkeit. 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 also eine eigene Datei aufgerufen wird.} ein eigener Prozeß gestartet. Das kostet natürlich Zeit und Speicher. Zeitkritische Anwendungen sind also kein Einsatzgebiet für Shell-Skripte. Die schreibt man besser in Perl, oder noch besser in einer `compilierten' Sprache wie C oder C++. Es stehen jedoch an der Shell viele sehr nützliche externe Kommandos zur Ver\-fü\-gung, die einem die Entwicklung entsprechender eigener Routinen ersparen. Diese externen Kommandos sind zudem in anderen Sprachen geschrieben worden, so daß sie schneller ablaufen als jedes Shell-Skript. Man kommt als Shell-Programmierer nicht sinnvoll um den Einsatz dieser Programme herum. In diesem Abschnitt sollen einige dieser Programme mit typischen Einsatzmöglichkeiten vorgestellt werden. Eine vollständige Beschreibung wäre (wenn überhaupt möglich) viel zu lang, um an dieser Stelle untergebracht zu werden. \textbf{Dies ist also nur ein grober Überblick, nicht mal annähernd eine vollständige Referenz!} Für ausführlichere Beschreibungen empfiehlt sich das Studium der Man-Pages oder der Kauf eines entsprechenden Buches (Siehe Anhang \ref{quellen}, `Quellen'). Am besten macht man natürlich beides. ;-) Eine globale Beschreibung aller gängigen Kommandos würde den Rahmen dieses Textes sprengen. Außerdem wäre es nicht leicht, das zu einer Aufgabe passende Werkzeug zu finden. Die Werkzeuge nach Aufgaben zu sortieren fällt allerdings auch nicht leicht. Die Entwickler der Kommandos versuchen, ihre Tools möglichst universell einsetzbar zu halten, also gibt es keine 1:1-Beziehung zwischen Problem und Lösung. Um sowohl das Finden eines Werkzeugs zu einem gegebenen Problem als auch das Finden einer Beschreibung zu einem gegebenen Werkzeug zu vereinfachen, und um die oben beschriebene n:m-Beziehung abzubilden, werden hier also zunächst typische Aufgaben beschrieben. Diese enthalten `Links' zu den in Frage kommenden Werkzeugen. Danach gibt es eine alphabetische Aufzählung der wichtigsten Kommandos. \section{Nägel...}\label{naegel} \subsection{Ein- und Ausgabe}\label{ein_und_ausgabe} Praktisch jedes Skript verwendet in irgendeiner Form die Ein- oder Ausgabe. Sei es in interaktiver Art auf dem Terminal, oder im Hintergrund auf Dateien. An dieser Stelle sei darauf hingewiesen, daß es auf unixoiden Systemen nicht 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 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. Und Schlußendlich können Prozesse sich sogenannte Named Pipes\index{Named Pipe} anlegen, in die sie schreiben oder aus denen sie lesen. Diese Kommandos sind also universell nützlich, nicht nur im Zusammenhang mit Dateien auf der Festplatte. \begin{itemize} \item \texttt{cat} (\ref{cat}): Dateien einlesen und ausgeben \item \texttt{echo} (\ref{echo}): Daten ausgeben \item \texttt{grep} (\ref{grep}): In Dateien suchen \item \texttt{head} (\ref{head}): Dateianfang ausgeben \item \texttt{printf} (\ref{printf}): Formatierte Datenausgabe \item \texttt{read} (\ref{read}): Zeilen einlesen \item \texttt{sort} (\ref{sort}): Zeilenweises Sortieren \item \texttt{tail} (\ref{tail}): Dateiende ausgeben \end{itemize} \subsection{Pfade und Dateien}\label{pfade_und_dateien} Eine der Hauptaufgaben von Shell-Skripten ist natürlich das Hantieren mit Dateien. In diesem Abschnitt geht es allerdings nicht um den Umgang mit Dateiinhalten, sondern vielmehr werden einige nützliche Tools im Umgang mit Dateien an sich vorgestellt. Auch hier gilt natürlich der Hinweis aus Abschnitt \ref{ein_und_ausgabe}: Eine Datei kann viel mehr sein als nur ein paar Daten im Filesystem. \begin{itemize} \item \texttt{basename} (\ref{basename}): Den Namen einer Datei (ohne Pfad) ausgeben \item \texttt{cp} (\ref{cp}): Dateien kopieren \item \texttt{chgrp} (\ref{chgrp}): Gruppen-ID einer Datei ändern \item \texttt{chmod} (\ref{chmod}): Zugriffsrechte einer Datei ändern \item \texttt{chown} (\ref{chown}): Eigentümer einer Datei ändern \item \texttt{dirname} (\ref{dirname}): Den Pfad zu einer Datei (ohne den Namen) ausgeben \item \texttt{find} (\ref{find}): Dateien suchen \item \texttt{mkdir} (\ref{mkdir}): Verzeichnisse anlegen \item \texttt{mv} (\ref{mv}): Dateien verschieben \item \texttt{rm} (\ref{rm}): Dateien löschen \item \texttt{rmdir} (\ref{rmdir}): Verzeichnisse löschen \item \texttt{touch} (\ref{touch}): Eine leere Datei anlegen, bzw. das Zugriffsdatum einer Datei ändern \item \texttt{xargs} (\ref{xargs}): Ausgaben eines Kommandos als Parameter eines anderen Kommandos benutzen \end{itemize} \subsection{Pipes manipulieren}\label{pipes_manipulieren}\index{Pipe|(textbf} Das Konzept der Pipes (Röhren) wird bereits in dem Kapitel über Befehlsformen (\ref{befehlsformen}) vorgestellt. Im wesentlichen besteht es darin, daß Daten von einem Programm an ein anderes weitergeleitet werden. Auf diese Weise entsteht eine sogenannte \textit{Pipeline}\index{Pipeline} aus mehreren Kommandos. Einige Kommandos sind für den Einsatz in einem solchen Konstrukt prädestiniert, obwohl die meisten auch alleine eingesetzt werden können. Übrigens gibt es einen goldenen Merksatz für die Auswahl einiger dieser Tools: Benutze nicht \texttt{awk}, wenn Du \texttt{sed} benutzen kannst. Benutze nicht \texttt{sed}, wenn Du \texttt{grep} benutzen kannst. Benutze nicht \texttt{grep}, wenn Du \texttt{cut} benutzen kannst. Der Grund dafür liegt darin, daß diese Programme bei jedem Einsatz gestartet und ausgeführt werden müssen. Und man sollte sich um der Performance willen den kleinsten geeigneten Hammer nehmen. \begin{itemize} \item \texttt{cut} (\ref{cut}): Teile einer Zeile ausschneiden \item \texttt{grep} (\ref{grep}): In einer Pipe suchen \item \texttt{sed} (\ref{sed}): In einer Pipe editieren \item \texttt{awk} (\ref{awk}): In einer Pipe editieren \item \texttt{sort} (\ref{sort}): Zeilenweises Sortieren \item \texttt{tee} (\ref{tee}): Datenstrom in einer Datei protokollieren \item \texttt{wc} (\ref{wc}): Zeilen, Wörter oder Zeichen zählen \end{itemize} \index{Pipe|)} \subsection{Prozeßmanagement}\label{prozessmanagement} Oft werden Shell-Skripte benutzt um Prozesse zu steuern oder zu überwachen. So werden Systemdienste üblicherweise über die Init-Skripte hoch- oder heruntergefahren. Es ist auch nicht sonderlich schwer, mit einem Skript einen `Wachhund' zu implementieren, der regelmäßig kontrolliert ob ein Prozeß noch läuft und ihn bei bedarf nachstartet. Für Aufgaben in diesem Bereich stehen unter anderem die folgenden Kommandos zur Verfügung. \begin{itemize} \item \texttt{kill} (\ref{kill}): Signal an einen Prozeß schicken \item \texttt{killall} (\ref{killall}): Signal an mehrere Prozesse schicken \item \texttt{ps} (\ref{ps}): Prozeßliste ausgeben \item \texttt{pgrep} (\ref{pgrep}): Bestimmte Prozesse suchen \item \texttt{pkill} (\ref{pkill}): Bestimmte Prozesse töten \end{itemize} \section{... und Hämmer}\label{haemmer} Um es noch einmal zu betonen: \textbf{Dies ist keine vollständige Kommandoreferenz!} Es werden nur die wichtigsten Kommandos vorgestellt, und deren Funktion wird in den meisten Fällen auch nur kurz angerissen. Für ausgiebigere Informationen empfehle ich entsprechende Bücher (siehe Anhang \ref{quellen}, `Quellen') und vor allem die Man-Pages. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsection{awk}\label{awk}\index{awk=\texttt{awk}|(textbf} TODO!!! awk \index{awk=\texttt{awk}|)} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsection{basename}\label{basename}\index{basename=\texttt{basename}|(textbf} Dem Tool \texttt{basename} wird als Parameter ein Pfad zu einer Datei übergeben. Der in der Angabe enthaltene Pfad wird abgeschnitten, nur der Name der eigentlichen Datei wird zurückgegeben. Siehe auch \texttt{dirname} (\ref{dirname}). \index{basename=\texttt{basename}|)} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsection{bc}\label{bc}\index{bc=\texttt{bc}|(textbf} Bei \texttt{bc} handelt es sich, ähnlich wie bei \texttt{expr} um einen Taschenrechner. Allerdings verfügt dieses Kommando um eine vergleichsweise komplexe Syntax, die auch Berechnungen mit hoher Genauigkeit zulassen. Für einfache Grundrechenaufgaben wie das Inkrementieren von Variablen sollte man entweder die eingebaute Arithmetik-Expansion der Shell (Siehe \ref{arithmetikexpansion}) oder das wesentlich ressourcenfreundlichere \texttt{expr} (Siehe \ref{expr}) benutzen. \index{bc=\texttt{bc}|)} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsection{cat}\label{cat}\index{cat=\texttt{cat}|(textbf} Auch \texttt{cat} ist ein oft unterbewertetes Tool. Seine Aufgabe besteht zwar lediglich darin, etwas von der Standardeingabe oder aus einer Datei zu lesen, und das dann auf der Standardausgabe wieder auszugeben. Allerdings leistet es an vielen, teilweise sehr unterschiedlich gelagerten Aufgaben wertvolle Dienste. Durch Umlenklung der Ausgabe können Dateien erzeugt und erweitert werden. So können mehrere Dateien per \texttt{cat datei1.txt datei2.txt > datei.txt} verkettet werden. Außerdem kann man mit einem Aufruf in der Art \texttt{cat datei.txt | kommando} Daten an ein Programm übergeben, das nur von der Standardeingabe lesen kann (Filter). \texttt{cat} verfügt über eine Reihe von Parametern, um die Ausgabe zu formatieren, so können mit \texttt{-n} bzw. \texttt{-b} die Zeilen numeriert werden, oder mit \texttt{-s} mehrere Zeilen zu einer einzigen zusammengefaßt werden. \index{cat=\texttt{cat}|)} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsection{chgrp}\label{chgrp}\index{chgrp=\texttt{chgrp}|(textbf} Jede Datei gehört einem Benutzer und einer Gruppe. Letzteres läßt sich mit \texttt{chgrp} einstellen. Als Parameter wird der Name oder die ID der Gruppe, sowie ein oder mehrere Dateinamen übergeben. Verzeichnisse können rekursiv mit dem Parameter \texttt{-R} bearbeitet werden. Der Eingentümer der Datei wird mit \texttt{chown} (Abschnitt \ref{chown}) festgelegt. \index{chgrp=\texttt{chgrp}|)} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsection{chmod}\label{chmod}\index{chmod=\texttt{chmod}|(textbf} In unixoiden Systemen verfügt jede Datei über eine Reihe von Attributen. Damit kann eine Menge gemacht werden, für den vollen Funktionsumfang empfiehlt sich das Studium der Man-Page oder einer umfangreicheren Kommandoreferenz. Hier nur das wichtigste in Kürze: Die Syntax lautet \texttt{chmod [options] mode file...}. Die einzig wichtige Option ist, analog zu \texttt{chgrp} und \texttt{chown} der Parameter \texttt{-R} für die rekursive Bearbeitung von Verzeichnissen. In der Syntax steht `file' für einen oder mehrere Dateinamen. Den Modus einer Datei sieht man, indem man \texttt{ls -l} darauf ansetzt, die Ausgabe wird im entsprechenden Abschnitt (\ref{ls}) beschrieben. Dort ist von den drei `rwx-Blöcken' die Rede, die die Berechtigungen für User (u), Group (g) und Other (o) angeben. Genau die können mittels \texttt{chmod} gesteuert werden. Zusätzlich gibt es hier noch die Angabe All (a), mit denen die Rechte für alle Benutzer verändert werden können. Hier wird der Modus gesteuert, indem direkt angegeben wird für wen welche Rechte gelten sollen. Mit `+' werden die Rechte erweitert, `-' nimmt Rechte und mit `=' werden die Rechte hart gesetzt. \texttt{chmod u+x datei} macht die Datei für den Besitzer ausführbar. Mit dem Parameter \texttt{u=rw,go=r} werden die Rechte auf `rw-r--r--' gesetzt, der Besitzer kann lesen und schreiben, alle anderen nur lesen. Neben dieser Art der Notation gibt es noch eine~--~wesentlich gängigere~--~numerische Schreibweise. Dabei werden die Berechtigungen in Form von Zahlen angegeben. Dabei werden drei Zahlen von eins bis sieben benutzt. Deren Bedeutung ergibt sich, wenn man sich die drei Stellen `rwx' als Binärzahl vorstellt. Das x steht an der niederwertigsten Stelle, erhält also den Wert 1. Das w steht für die 2 und r für 4. In Summe ergeben diese Zahlen die Berechtigung. Also ist `rwx' gleichbedeutend mit 4+2+1=7. `rw' entspricht 4+2=6. Die reine Leseberechtigung `r' bleibt als 4 stehen. Zur Verdeutlichung ein paar Beispiele, wo es möglich ist in beiden Notationen: \LTXtable{\textwidth}{tab_kommandos_chmod_beispiele.tex} Am wichtigsten sind also die Aufrufe \texttt{chmod 644 datei} und \texttt{chmod 755 datei}, je nachdem ob die Datei ausführbar sein soll oder nicht. \index{chmod=\texttt{chmod}|)} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsection{chown}\label{chown}\index{chown=\texttt{chown}|(textbf} Mit \texttt{chown} lassen sich Benutzer- und Gruppen-ID von Dateien und Verzeichnissen festlegen. Mit dem Parameter \texttt{-R} sogar rekursiv für Verzeichnisse. Ein einzelner Parameter gibt die User-ID oder den Namen des zukünfigen Benutzers an, in der Form name:gruppe können sowohl User- als auch Gruppen-ID gleichzeitig geändert werden. Will man lediglich die Gruppen-ID ändern, benutzt man das Kommando \texttt{chgrp} (Abschnitt \ref{chgrp}). \index{chown=\texttt{chown}|)} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsection{chpasswd}\index{chpasswd=\texttt{chpasswd}|(textbf} Mit diesem Kommando bietet sich dem Administrator des Systems die Mög\-lich\-keit, scriptgesteuert die Paßwörter für neue Benutzer zu vergeben. Manuell ändert man ein Paßwort mit dem Kommando \texttt{passwd}\index{passwd=\texttt{passwd}}, allerdings löscht (flusht) dieses Programm die Standard-Eingabe, bevor es das neue Paßwort erwartet. Somit lassen sich Paßwörter mit \texttt{passwd} nur interaktiv ändern\footnote{Es gibt auch einen anderen Weg: Man kann \texttt{passwd} auch mittels \texttt{expect} fernsteuern. Allerdings ist diese Methode weniger elegant.}. Das Kommando wird in der Form \texttt{echo }\textit{name}\texttt{:}\textit{pass}\texttt{ | chpasswd} aufgerufen. Es ist auch möglich, dem Programm eine Datei mit vielen Name / Paßwort-Kombinationen an die Standard-Eingabe zu übergeben: \texttt{cat }\textit{passwoerter.txt}\texttt{ | chpasswd} Allerdings sollte dabei aus Sicherheitsgründen darauf geachtet werden, daß diese Datei nicht allgemein lesbar ist. \index{chpasswd=\texttt{chpasswd}|)} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsection{cp}\label{cp}\index{cp=\texttt{cp}|(textbf} Mit \texttt{cp} werden Dateien kopiert. Die wichtigsten Optionen im Zusammenhang mit Skripten sind \texttt{-f} und \texttt{-R}. Ersteres erzwingt (force) das Kopieren, falls an der Zielstelle schon Dateien existieren werden sie überschrieben. Letzteres ermöglicht ein rekursives Kopieren. Verzeichnisse~--~auch leere~--~können nur mit \texttt{-R} kopiert werden. \index{cp=\texttt{cp}|)} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsection{cut}\label{cut}\index{cut=\texttt{cut}|(textbf} Wie der Name (fast) schon sagt, kann man mit diesem Kommando Zeilen zerschneiden. Mit den Parametern \texttt{-c} (Character) oder \texttt{-f} (Field) wird bestimmt, in welcher Einheit die Schnittstellen abgesteckt werden sollen. Falls die Zeilen in Felder zerteilt werden sollen, kann zusätzlich mittels \texttt{-d} der Delimiter, also das Trennzeichen bestimmt werden. Wird das nicht explizit getan, wird der Tabulator benutzt. Dieser Definition folgt die Angabe des zu behaltenden Bereichs. Dafür kann eins der Formate N, N-, N-M oder -M benutzt werden. \LTXtable{\textwidth}{tab_kommandos_cut_beispiele.tex} \index{cut=\texttt{cut}|)} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsection{dirname}\label{dirname}\index{dirname=\texttt{dirname}|(textbf} Analog zu \texttt{basename} (\ref{basename}) gibt \texttt{dirname} nur die Pfad-Komponente einer angegebenen Datei zurück. \index{dirname=\texttt{dirname}|)} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsection{echo}\label{echo}\index{echo=\texttt{echo}|(textbf} Dies ist wohl der grundlegendste Befehl, der in einem Skript verwendet werden kann. Er ist die Voraussetzung, um eines der wichtigsten Werkzeuge der Kybernetik auch mittels eines Shell-Skriptes effizient umzusetzen: Hello World. :-) Die eigentliche Aufgabe dieses Befehls dürfte jedem bekannt sein, der sich bis zu dieser Stelle durchgearbeitet hat. Allerdings wissen viele nicht, daß auch der echo-Befehl über Parameter verfügt. Zumindest zwei davon erweisen sich in der Praxis oft als sehr hilfreich: \LTXtable{\textwidth}{tab_kommandos_echo_parameter.tex} \index{echo=\texttt{echo}|)} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsection{eval}\label{eval}\index{eval=\texttt{eval}|(textbf} Die Wirkungsweise von \texttt{eval} läßt sich wohl am ehesten durch ein kleines Beispiel erklären: \LTXtable{\textwidth}{tab_kommandos_eval_beispiel.tex} Bevor eine Zeile in der Shell tatsächlich ausgeführt wird, wird sie von der Shell expandiert, bzw. evaluiert. Der letzte Begriff deutet schon an was damit gemeint ist: Enthaltene Variablennamen werden durch ihre Werte ersetzt. Das Kommando \texttt{eval} führt die Zeile die durch die Expansion entstanden ist noch einmal aus. So ist es möglich, Variablennamen aus den Inhalten anderer Variablen zu bilden. 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 beispielsweise mittels \texttt{eval echo \textbackslash\$arr\$index} ausgegeben werden, dabei ist \texttt{arr} der Name des Arrays und \texttt{index} der Name der Variablen, die den Index des auszugebenden Elementes enthält. \index{eval=\texttt{eval}|)} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsection{expr}\label{expr}\index{expr=\texttt{expr}|(textbf} Mit dem Kommando \texttt{expr} verfügt die Shell praktisch über einen Taschenrechner für einfache Berechnungen. Für komplexe Aufgaben bietet sich das Tool \texttt{bc} an, näheres dazu steht in Abschnitt \ref{bc}. Genau genommen kann man mit \texttt{expr} nicht nur Berechnungen durch\-füh\-ren, sondern ganz allgemein `Ausdrücke evaluieren'. Damit ist gemeint, daß es zum Beispiel auch Operatoren für Pattern-Matching gibt. Die wichtigsten Operatoren lauten wie folgt: \LTXtable{\textwidth}{tab_kommandos_expr_parameter.tex} Bei einigen Sonderzeichen ist deren Bedeutung in der Shell zu berücksichtigen, sie sind also durch Anführungszeichen oder Backslashes zu quoten: \texttt{i=`expr \$i \textbackslash{}* 3`}. Eine andere Möglichkeit für einfache Rechnungen besteht in der sogenannten Arith\-me\-tik-Ex\-pan\-sion (Siehe \ref{arithmetikexpansion}). \index{expr=\texttt{expr}|)} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsection{find}\label{find}\index{find=\texttt{find}|(textbf} TODO!!! find Siehe auch: Abschnitt \ref{beispiele_suchen_dateien}. \index{find=\texttt{find}|)} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsection{grep}\label{grep}\index{grep=\texttt{grep}|(textbf} Das Tool \texttt{grep} stammt aus dem Standard-Repertoire eines jeden Sys\-tem\-ad\-mi\-ni\-stra\-tors. Mit seiner Hilfe kann in einer oder mehreren Dateien, oder eben auch in einem Datenstrom nach dem Auftreten bestimmter regulärer Ausdrücke (siehe \ref{mustererkennung}) gesucht werden. Die folgende Tabelle stellt einige der vielen Parameter vor: \LTXtable{\textwidth}{tab_kommandos_grep_parameter.tex} Siehe auch: Abschnitt \ref{beispiele_suchen}. \index{grep=\texttt{grep}|)} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsection{head}\label{head}\index{head=\texttt{head}|(textbf} \texttt{head} ist das Gegenstück zu \texttt{tail} (Siehe \ref{tail}). Hier werden allerdings nicht die letzten Zeilen angezeigt, sondern die ersten. \index{head=\texttt{head}|)} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsection{kill}\label{kill}\index{kill=\texttt{kill}|(textbf} TODO!!! kill Übrigens: Die landläufige Annahme ist, daß man mit dem \texttt{kill}-Kom\-man\-do Prozesse `umbringt'. Das ist zwar wahr, aber nicht die ganze Wahrheit. \index{kill=\texttt{kill}|)} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsection{killall}\label{killall}\index{killall=\texttt{killall}|(textbf} 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, oder will man das Signal an mehrere Prozesse schicken, kann dieses Kommando eine große Hilfe darstellen. Mit dem Parameter \texttt{-i} wird vor jedem Signal interaktiv gefragt, ob es geschickt werden soll. Mit \texttt{-v} wird angegeben, ob die Signale erfolgreich versandt wurden, \texttt{-q} hingegen unterdrückt die Ausgaben. Da ein Prozeß nach einem Signal nicht notwendigerweise sofort stirbt, gibt es eine Option \texttt{-w}. Diese Veranlaßt \texttt{killall} zu warten, bis alle Empfänger tot sind. Dieser Parameter ist allerdings mit Vorsicht zu genießen: Wenn der Prozeß sich weigert zu sterben, wartet \texttt{killall} ewig. Eine ähnliche Funktionalität bietet auch das Kommando \texttt{pkill} (Abschnitt \ref{pkill}), \texttt{killall} hat aber den Vorteil daß es auf mehr Systemen zur Verfügung steht. \index{killall=\texttt{killall}|)} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsection{ls}\label{ls}\index{ls=\texttt{ls}|(textbf} Die linke Spalte der Ausgabe zeigt die bestehenden Berechtigungen. Es ist ein Block in der Form `drwxrwxrwx'. An Stelle des d können auch andere Buchstaben stehen, hier wird der Dateityp angegeben, also ob es sich um eine einfache Datei (-), ein Verzeichnis (d), einen Link (l) oder ähnliches\footnote{Siehe Man-Page} handelt. An Stelle der rwx-Blöcke können auch Striche stehen, die stehen für nicht gesetzte Attribute. TODO!!! ls \index{ls=\texttt{ls}|)} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsection{mkdir}\label{mkdir}\index{mkdir=\texttt{mkdir}|(textbf} Mit diesem Kommando werden Verzeichnisse angelegt. Dabei kann mit \texttt{-m} angegeben werden, welche Berechtigungen das Verzeichnis bekommen soll. Mit \texttt{-p} werden bei Bedarf auch Parent-Verzeichnisse angelegt, es entsteht also ein kompletter Pfad. Entfernen lassen sich Verzeichnisse mit \texttt{rmdir} (Abschnitt \ref{rmdir}). \index{mkdir=\texttt{mkdir}|)} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsection{mv}\label{mv}\index{mv=\texttt{mv}|(textbf} Dateien und Verzeichnisse können mit dem Kommando \texttt{mv} verschoben werden. Falls am Ziel schon Dateien existieren erzwingt der Parameter \texttt{-f} die Aktion, die alten Dateien werden überschrieben. Mit \texttt{-i} wird der Vorgang interaktiv, vor jeder Dateibewegung wird nachgefragt. \index{mv=\texttt{mv}|)} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsection{pgrep}\label{pgrep}\index{pgrep=\texttt{pgrep}|(textbf} Eine häufig wiederkehrende Aufgabe ist es, zu sehen ob ein bestimmter Prozeß existiert oder nicht. Falls das Kommando \texttt{pgrep} zur Verfügung steht, kannn man auf das Konstrukt mit \texttt{ps} und \texttt{grep} verzichten. Der folgende Aufruf liefert alle Prozeß-IDs, deren Name httpd enthält, inclusive des vollen Kommandos: \texttt{pgrep -lf httpd} Über weitere Parameter läßt sich genauer spezifizieren, wonach gesucht werden soll, hier die wichtigsten: \LTXtable{\textwidth}{tab_kommandos_pgrep_parameter.tex} Die Ausgabe enthält per Default nur die Prozeß-IDs der Fundstellen. Diese läßt sich als Parameter für andere Programme benutzen. Das folgende Beispiel liefert detaillierte Informationen über alle xterm-Prozesse: \texttt{ps -fp \$(pgrep -d, -x xterm)} Siehe auch: Abschnitt \ref{beispiele_suchen_prozesse}. \index{pgrep=\texttt{pgrep}|)} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsection{pkill}\label{pkill}\index{pkill=\texttt{pkill}|(textbf} Dieses Kommando ist eng verwandt mit \texttt{pgrep} (Siehe Abschnitt \ref{pgrep}), es versteht im Wesentlichen die gleichen Parameter. Allerdings werden die Fundstellen hier nicht ausgegeben. Wie der Name schon andeutet, werden hiermit Prozesse umgebracht. Da man hier mit einem Kommando unter Umständen viele Prozesse beendet, sollten \textbf{die verwendeten Parameter genau unter die Lupe} genommen werden, um `Kollateralschäden' zu vermeiden. :-) Es besteht auch die Möglichkeit, den Prozessen andere Signale zuzuschicken, diese Funktion wird im Abschnitt zu \texttt{kill} (\ref{kill}) näher beschrieben. Das folgende Kommando veranlaßt beispielsweise den Syslog-Daemon, seine Konfiguration neu einzulesen: \texttt{pkill -HUP syslogd} Das Kommando \texttt{killall} (Abschnitt \ref{killall}) bietet eine ähnliche Funktionalität, allerdings fehlen ihm einige Parameter. Trotzdem sollte im Zweifel \texttt{killall} benutzt werden, da es auf mehr Systemen zur Verfügung steht. \index{pkill=\texttt{pkill}|)} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsection{printf}\label{printf}\index{printf=\texttt{printf}|(textbf} Analog zum gleichnamigen Befehl in Programmiersprachen wie Perl oder C dient \texttt{printf} der formatierten Ausgabe von Daten. Als Parameter wird ein sogenannter Format-String und eine Liste von auszugebenden Daten mitgegeben. Dabei enthält der Format-String eine Reihe von Platzhaltern, die nach bestimmten Regeln durch die Daten ersetzt werden. Der Format-String folgt im Wesentlichen den gleichen Regeln wie in der C-Version. Näheres dazu erfährt man mit \texttt{man 3 printf}. Hier die wichtigsten Parameter für den Format-String: \LTXtable{\textwidth}{tab_kommandos_printf_parameter.tex} Besonders nützlich ist dieses Kommando bei der tabellarischen Ausgabe von Daten. Im folgenden Beispiel werden alle Benutzernamen, deren Home-Verzeichnisse und Default-Shells aus der Datei \texttt{/etc/passwd} extrahiert und übersichtlich ausgegeben: \footnotesize \begin{listing}[2]{1} #!/bin/sh IFS=: while read user pass uid gid name home shell; do printf "%-15s %-25s %s\n" $user $home $shell done < /etc/passwd \end{listing} \normalsize Zur Erinnerung: Die vordefinierte Variable \texttt{\$IFS}\index{\$IFS=\texttt{\$IFS}} ist der Feld-Separator, die Eingabezeilen werden also als Doppelpunkt-separierte Liste gesehen. Näheres dazu steht im Abschnitt über vordefinierte Variablen (\ref{vordefinierte_variablen}). \index{printf=\texttt{printf}|)} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsection{ps}\label{ps}\index{ps=\texttt{ps}|(textbf} TODO!!! ps Siehe auch: Abschnitt \ref{beispiele_suchen_prozesse}. \index{ps=\texttt{ps}|)} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsection{read}\label{read}\index{read=\texttt{read}|(textbf} Mit dem Kommando \texttt{read} kann man Eingaben von der Standard-Eingabe\index{Standard-Eingabe} lesen. Dabei wird üblicherweise einer oder mehrere Variablennamen übergeben. Dem ersten Namen wird das erste eingegebene Wort zugewiesen, dem zweiten das zweite Wort usw. Dem letzen Variablennamen wird der verbleibende Rest der Eingabezeile zugewiesen. Wenn also nur ein Variablenname angegeben wird, erhält dieser die komplette Eingabezeile. Wenn weniger Worte gelesen werden als Variablen angegeben sind, enthalten die verbleibenden Variablen leere Werte. Als Wort-Trennzeichen dienen alle Zeichen, die in der vordefinierten Variable \texttt{\$IFS}\index{\$IFS=\texttt{\$IFS}} enthalten sind (siehe Abschnitt \ref{vordefinierte_variablen}). Wenn keine Variablennamen angegeben werden, wird die Eingabe in der Variable \texttt{REPLY} abgelegt. Normalerweise wird eine Eingabezeile mit einem Newline abgeschlossen. Mit dem Parameter \texttt{-d} ist es möglich, ein anderes Zeilenendezeichen anzugeben. Beispielsweise liest \texttt{read -d \dq~\dq~var} alle Zeichen bis zum ersten Leerzeichen in die Variable \texttt{var} ein. Wenn nur eine bestimmte Zahl von Zeichen gelesen werden soll, kann diese durch den Parameter \texttt{-n} angegeben werden. Der Befehl \texttt{read -n 5 var} liest die ersten fünf Zeichen in die Variable \texttt{var} ein. Demzufolge kann ein Skript durch ein \texttt{read -n 1} dazu gebracht werden, auf einen einzelnen Tastendruck~--~nicht zwingend ein Return~--~zu warten. Mit dem Parameter \texttt{-p} kann man einen Prompt, also eine Eingabeaufforderung ausgeben lassen. \texttt{read -p \dq{}Gib was ein:\dq~var} schreibt also erst den Text \textit{Gib was ein:} auf das Terminal, bevor die Eingaben in die Variable \texttt{var} übernommen werden. Dieser Prompt wird nur an einem interaktiven Terminal ausgegeben, also nicht in einem Skript das seine Eingaben aus einer Datei oder aus einem Stream erhält. Sonderzeichen können während der Eingabe normalerweise mittels eines Backslash vor der Interpretation geschützt werden. Ein Backslash vor einem Newline bewirkt also eine mehrzeilige Eingabe. Dieses Verhalten kann mit dem Parameter \texttt{-r} abgeschaltet werden. Wenn die Eingabe von einem Terminal kommt und nicht auf dem Bildschirm erscheinen soll, zum Beispiel bei Paßwortabfragen, kann die Ausgabe mit dem Parameter \texttt{-s} (Silent) unterdrückt werden. Mit \texttt{-t} kann ein Time-Out definiert werden, nach dessen Ablauf das Kommando mit einem Fehler abbricht. Dieser Parameter ist nur bei interaktiver Eingabe oder beim Lesen aus einer Pipe aktiv. Der Rückgabewert des \texttt{read}-Kommandos ist 0, es sei denn es trat ein Timeout oder ein EOF auf. \index{read=\texttt{read}|)} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsection{rm}\label{rm}\index{rm=\texttt{rm}|(textbf} Mit diesem Kommando können Dateien und Verzeichnisse gelöscht werden. Dabei kann man vorsichtig vorgehen, indem man mit \texttt{-i} dafür sorgt, daß jeder Löschvorgang be\-stä\-tigt werden muß. Oder rabiat, indem man mit \texttt{-f} das Löschen erzwingt. Verzeichnisse können mit dem Parameter \texttt{-R} entfernt werden, im Gegensatz zu \texttt{rmdir} werden dann auch sämtliche enthaltenen Dateien und Unterverzeichnisse gelöscht. Die GNU-Version von \texttt{rm} unterstützt zusätzlich den Parameter \texttt{-v}, mit dem jeder Löschvorgang ausgegeben wird. \index{rm=\texttt{rm}|)} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsection{rmdir}\label{rmdir}\index{rmdir=\texttt{rmdir}|(textbf} Mit \texttt{rmdir} werden Verzeichnisse gelöscht. Das funktioniert nur, wenn sie leer sind. Mit \texttt{-p} kann ein kompletter Verzeichnispfad gelöscht werden, will sagen: Alle höher liegenden Verzeichnisse im angegebenen Pfad werden gelöscht. Voraussetzung ist hier natürlich auch, daß die Verzeichnisse nichts außer dem angegebenen Unterverzeichnis enthalten. Angelegt werden Verzeichnisse mit \texttt{mkdir} (Abschnitt \ref{mkdir}), nicht-leere Verzeichnisse können rekursiv mit \texttt{rm -r} (Abschnitt \ref{rm}) gelöscht werden. \index{rmdir=\texttt{rmdir}|)} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsection{script}\label{script}\index{script=\texttt{script}|(textbf} Dieses Kommando eignet sich vorzüglich für das Debuggen fertiger Skripte. Man ruft es in Verbindung mit einem Dateinamen auf. Dieser Aufruf startet eine neue Shell, in der man beliebige Kommandos ausführen kann. Wenn man fertig ist, beendet man den script-Befehl durch die Eingabe von \texttt{exit}, \texttt{logout} oder Druck der Tastenkombination \Ovalbox{CTRL}+\Ovalbox{d} (EOF). Script schreibt alle Ein- und Ausgaben die an dem Terminal vorgenommen werden in die angegebene Datei. So kann man auch interaktive Skripte relativ leicht debuggen, da sowohl Ein- als auch Ausgaben in dem Logfile sichtbar sind. \index{script=\texttt{script}|)} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsection{sed}\label{sed}\index{sed=\texttt{sed}|(textbf} TODO!!! sed \index{sed=\texttt{sed}|)} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsection{seq}\label{seq}\index{seq=\texttt{seq}|(textbf} Oft wird eine auf- oder absteigende Sequenz aufeinanderfolgender Zahlen benötigt, beispielsweise um eine Schleife 100 mal zu durchlaufen. Es ist nicht sehr performant bei jedem Schleifendurchlauf hochzuzählen und dann die entstandene Zahl mit dem Limit zu vergleichen. Daher nimmt man an der Stelle \texttt{seq} zur Hilfe. Die zu zählenden Werte werden durch drei unterschiedliche Arten der Parametrisierung definiert: Ein Aufruf in der Form \texttt{seq 10} gibt die Zahlen von 1 bis 10 aus. Mit \texttt{seq 10 20} wird von 10 bis 20 gezählt, und \texttt{seq 20 -2 10} zählt in zweierschritten rückwärts von 20 nach 10. Per default kommen die Werte zeilenweise, mit dem Parameter \texttt{-s} kann aber auch ein anderes Trennzeichen definiert werden. Will man etwas numerieren und später nach den Zahlen sortieren, ist es sinnvoll wenn `schmalere' Zahlen mit führenden Nullen aufgefüllt werden. Das erreicht man mit dem Parameter \texttt{-w}. \index{seq=\texttt{seq}|)} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsection{sleep}\label{sleep}\index{sleep=\texttt{sleep}|(textbf} Das Kommando \texttt{sleep} veranlaßt die Shell, für eine angegebene Zeit zu warten. Die Zeit wird dabei in Sekunden angegeben. In der GNU-Variante von \texttt{sleep} kann die Einheit der angegebenen Zeitspanne durch Suffixe definiert werden: \texttt{sleep 10s} schläft zehn Sekunden, \texttt{sleep 10m} zehn Minuten. Genauso werden Stunden (h) und Tage (d) definiert. Außerdem kann die GNU-Variante auch mit nicht-Integer Zeiten arbeiten: \texttt{sleep 0.5} schläft eine halbe Sekunde. \index{sleep=\texttt{sleep}|)} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsection{sort}\label{sort}\index{sort=\texttt{sort}|(textbf} Mit diesem Befehl wird wie der Name schon andeutet sortiert. Wenn kein Dateiname als Parameter angegeben wird, liest \texttt{sort} von der Standard-Eingabe. Geschrieben wird immer auf der Standard-Ausgabe. Man kann sich vorstellen, daß ein solches Kommando recht flexibel sein muß, daher stehen eine Menge Parameter zur Verfügung: \LTXtable{\textwidth}{tab_kommandos_sort_parameter.tex} Die Sortierung nach der Spalte (mit \texttt{-k}) ist etwas tricky. Die genaue Syntax wird in der Man-Page mit \texttt{-k POS1[,POS2]} angegeben, das bedeutet man muß einen Parameter angeben, man kann bei Bedarf einen zweiten angeben. Bei der Sortierung wird dann der Bereich ab POS1, bzw. der Bereich zwischen POS1 und POS2 berücksichtigt. Dabei lautet die Syntax für POS \texttt{F[.C][OPTS]}. Dabei gibt F die Feldnummer an (siehe Parameter \texttt{-t}). Wenn nicht nach dem Feld an sich sortiert werden soll, kann C die Position des Zeichens innerhalb des Feldes angeben. Und als ob das noch nicht kompliziert genug wäre, kann man dem ganzen Konstrukt noch einen einbuchstabigen Parameter für die Sortier-Option mitgeben. Wenn das angegebene Feld nicht existiert wird nach der ganzen Zeile sortiert. OK, Beispiele: \LTXtable{\textwidth}{tab_kommandos_sort_beispiele.tex} Weitere Parameter verrät wie immer die Man-Page. \index{sort=\texttt{sort}|)} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsection{tail}\label{tail}\index{tail=\texttt{tail}|(textbf} Der Befehl \texttt{tail} gibt die letzten zehn Zeilen einer Datei aus. Wenn kein Dateiname (oder ein \texttt{-}) angegeben wird, liest \texttt{tail} von der Standard-Eingabe. Man kann die Anzahl der ausgegebenen Zeilen mit dem Parameter \texttt{-n} steuern. Mit dem Parameter \texttt{-f} (follow) gibt \texttt{tail} neue Zeilen aus, sobald sie an die Datei angehängt werden. \index{tail=\texttt{tail}|)} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsection{tee}\label{tee}\index{tee=\texttt{tee}|(textbf} Dies ist praktisch ein T-Stück für Pipes. \texttt{tee} liest von seiner Standard-Eingabe, und gibt alle Eingaben direkt auf der Standard-Ausgabe wieder aus. Nebenbei werden die Ausgaben in eine oder mehrere Dateien geschrieben. Wenn die Ausgabedateien schon existieren, werden sie überschrieben. Dieses Verhalten kann mit dem Parameter \texttt{-a} geändert werden. \index{tee=\texttt{tee}|)} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsection{touch}\label{touch}\index{touch=\texttt{touch}|(textbf} Mit diesem Kommando kann man einerseits Dateien anlegen wenn sie nicht existieren, und andererseits die Änderungs- und Zugriffszeiten einer Datei ändern. Ohne die Angabe weiterer Parameter wird die Datei erzeugt wenn sie nicht existierte, bzw. in ihrer Änderungs- und Zugriffszeit auf die aktuelle Zeit gesetzt. Mit dem Parameter \texttt{-a} wird nur die Zugriffs-, mit \texttt{-m} nur die Änderungszeit gesetzt. Mit \texttt{-c} kann die Erstellung einer neuen Datei unterdrückt werden. Die eingesetzte Zeit kann auch durch die Parameter \texttt{-t} bzw. \texttt{-d} angegeben werden. Mit \texttt{-r} kann die Zeit der einer angegebenen Referenzdatei angepaßt werden. \index{touch=\texttt{touch}|)} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsection{wc}\label{wc}\index{wc=\texttt{wc}|(textbf} Wie der Name schon suggeriert\footnote{Oder etwa nicht?!? ;-)} kann man mit diesem Kommando Wörter zählen (word count). Gezählt wird entweder in einer Datei, oder~--~wenn kein Dateiname angegeben wurde~--~in der Standardeingabe. Weitaus häufiger wird aber der Parameter \texttt{-l} benutzt, mit dem sich die Zeilen zählen lassen. Weiterhin kann man Bytes (\texttt{-c}) oder Zeichen (\texttt{-m}) zählen lassen. Der Parameter \texttt{-L} gibt die Länge der längsten enthaltenen Zeile aus. \index{wc=\texttt{wc}|)} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsection{who}\label{who}\index{who=\texttt{who}|(textbf} Das Kommando \texttt{who} gibt eine Liste aller angemeldeten Benutzer, zusammen mit deren aktueller Konsole und der Anmeldezeit aus. \index{who=\texttt{who}|)} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsection{xargs}\label{xargs}\index{xargs=\texttt{xargs}|(textbf} Bisweilen kommt man in die Verlegenheit, versehentlich zu lange Einzeiler geschrieben zu haben. Neben den Fällen, in denen der Tipp-Eifer überhand genommen hat handelt es sich in aller Regel um Zeilen in der Art `\texttt{grep 'text' \$(find / -name \textbackslash*.txt)}'. Dieses Kommando sucht alle Dateien mit der Endung txt, die im System vorhanden sind. Diese werden `in die Kommandozeile eingebaut'. Wenn sehr viele Dateien gefunden werden, wird die Zeile zu lang für die Shell\footnote{Die maximale Länge der Kommandozeile unterscheidet sich von System zu System}. 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 in der Form `\texttt{find / -name \textbackslash*.txt -exec grep 'text' \{\} \textbackslash;}'. 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 `\texttt{find / -name \textbackslash*.txt | xargs grep 'text'}' umgangen. 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 obigen Beispiel nicht einmal pro Fundstelle. Neben einigen anderen Parametern informiert die Manpage über die Option \texttt{-r}. Damit kann vermieden werden, daß \texttt{xargs} das Kommando startet wenn keine Eingabe vorhanden ist. Bezogen auf das angegebene Beispiel würde \texttt{grep} ohne Dateinamen gestartet, wenn \texttt{find} nichts findet. Es würde auf Input von der Standardeingabe warten, der aber wahrscheinlich nicht kommt. Das Skript würde hängen, wenn der Parameter \texttt{-r} nicht angewandt würde. \index{xargs=\texttt{xargs}|)}