Listing 7
#!/bin/bash
PATH=/bin:/usr/bin # setzt den Pfad
. /usr/local/sbin/functions.bash # Datei hier einbinden
printf "USER\tGB USED\n" # Kopfzeile für Bericht drucken
for WHO in $(</usr/local/sbin/ckusers); do
HOMESUM=`eval du -s ~$WHO | awk '{print $1}'`
TMPLIST=$( ls -lR --block-size 1024 $(</usr/local/bin/ckdirs) |\
egrep "^.......... +[0-9]+ $WHO" | awk '{print $5}' )
TSUM=0
for N in $TMPLIST; do
TSUM=$(( $TSUM+$N ))
done
TOT=$(( $HOMESUM+$TSUM ))
to_gb $WHO $TOT
done
Eine For-Schleife bildet das zentrale Konstrukt dieses Skripts. Innerhalb der Schleife erhält eine Variable bei jedem Durchgang einen neuen Wert. Das Schlüsselwort in verweist auf die Liste von Werten, der separate Befehl do leitet die eigentlichen Operationen ein. Die Schleife endet mit done, sobald sie alle Elemente der Liste abgearbeitet hat.
Im Beispiel erhält die Variable WHO immer das nächste Element aus der Datei ckusers. Das Konstrukt $(<file) arbeitet als Abkürzung für $(cat file).
Die Definition von HOMESUM verwendet ein Backtick-Konstrukt, um die Gesamtgröße des Home-Verzeichnisses eines Benutzers aus der Ausgabe von du -s via Awk zu extrahieren. Der Befehl eval bewirkt, dass das Kommando du das Konstrukt ~$WHO als Tilde-Schreibweise für das Benutzerverzeichnis interpretiert.
Die Definition von TMPLIST verwendet Befehlssubstitution zum Herausfiltern und Einfügen des Größe-Feldes aller Zeilen (via Awk) in der Ausgabe von ls -lR, die den Elementen des aktuellen Benutzers entsprechen (festgestellt durch Egrep). Der Befehl ls prüft alle Verzeichnisse, die die Datei ckdirs auflistet. Er verwendet die Option --block-size, um das Ergebnis in der gleichen Größenordnung anzuzeigen, wie es du verwendet (KByte).
Sobald alles abgearbeitet ist, enthält TMPLIST eine Liste von Zahlen – je eine pro Datei, die zum aktuellen Benutzer gehören. Die zweite For-Schleife addiert die Zahlen von TMPLIST in TSUM. Diese Schleife weist die gleiche Struktur auf wie die obige. Als Variable agiert in diesem Fall N.
Die Bash bietet über das Konstrukt $(( Mathematischer Ausdruck )) eingebaute Ganzzahl-Arithmetik. Das Skript verwendet dieses Konstrukt zweimal. Eine Funktion namens to_gb (Listing 8) erledigt das Ausdrucken jeder Berichtszeile.
Listing 8
to_gb()
{
# arguments: user usage-in-KB
local MB D1 D2 USER # lokale Variablen
USER=$1
MB=$(( $2/1024 )) # konvertieren in MByte
D1=$(( $MB/1000 )) # Ausgabe ganzzahlig in GByte
D2=$(( $MB-($D1*1000) )) # Rest berechnen
# display abcd MB as: a.bcd GB
printf "%s\t%s\n" $USER $D1.${D2:0:1}
return
}
Die Bash setzt voraus, dass Sie Funktionen vor dem Einsatz definieren. Dazu bietet es sich an, Funktionen in einer externen Datei zu speichern und über den Punktbefehl in Skripte einzubinden. Im Beispiel aus Listing 7 liegt die Funktion in der Datei functions.bash.
Die Funktion to_gb() beginnt mit der Definition einiger lokaler Variablen. Damit ignoriert sie jegliche Bedeutung, die diese Namen im aufrufenden Skript eventuell haben könnten, und die lokalen Werte gelangen nicht in den übergeordneten Kontext zurück.
Der größte Teil der Funktion besteht aus arithmetischen Operationen. Die Bash unterstützt ausschließlich Ganzzahl-Arithmetik. Möchten Sie eine einigermaßen genaue Gesamtgröße in GByte anzeigen, müssen Sie dazu einen gängigen Trick nutzen: Sie entnehmen zuerst die Ganzzahlen, dann den Rest des GByte-Wertes und setzen die Ausgabe per Hand zusammen.
Haben Sie zum Beispiel 2987 MByte und dividieren dies durch 1024, wäre das gerundete Ergebnis 2 GByte. Um ein genaueres Ergebnis anzuzeigen, dividieren Sie stattdessen zuerst 2987 durch 1000 (D1=2), dann berechnen Sie 2987-(2*1000). Der Wert für D2 beträgt dann 987. Anschließend geben Sie die Variable D1, ein Komma und dann die erste Ziffer von D2 ein: Das Ergebnis lautet dann 2.9. So sähe eine beispielhafte Ausgabe des Skripts aus:
BENUTZER BELEGT in GB andrea 80.5 karsten 14.3 monika 0.3
Der Befehl printf ermöglicht eine formatierte Ausgabe. Er erfordert einen Format-String, gefolgt von Variablen, um den Ausdruck zu befüllen. Kennbuchstaben hinter Prozentzeichen geben an, wo die Variablen-Inhalte landen. Im Beispiel bestimmt %s die Stellen, an denen die Funktion die Werte einfügt. Hier gibt der Buchstabe s an, dass es sich um eine Zeichenkette handelt.
Die Zeichen \t und \n im Format-String entsprechen den Steuerzeichen Tabulator und Zeilenumbruch. Wollen Sie die Zeile explizit beenden, müssen Sie Letzteres angeben.
Das nächste Skript (Listing 9) berechnet Fakultäten und veranschaulicht eine andere Art von For-Schleife, die dem ähnelt, was in vielen Programmiersprachen üblich ist, wie zum Beispiel in C.
Listing 9
#!/bin/bash F=1 for (( I=$1 ; I>1 ; I-- )); do F=$(( $F*$I )) done echo $1'! = '$F exit 0

