command substitution

In einem der vorangegangenen Kommandos haben wir gelernt wie die Shell den Inhalt einver Variable an einer Stelle in der "commandline" einsetzten kann:

echo $USER

Dieser Befehl würde den Inhalt der Environment-Varibale $USER an der Stelle dort einsetzen und der "echo"-Befehl würde diesen Wert dann ausgeben.

Anstatt den Inhalt einer Variable in die Commandline einzusetzen, kann man auch die Ausgabe eines beliebigen Befehls setzen. also z.B.:

echo heute ist der $(date)

das "$( )" wird von der Shell ersetzt mit der Ausgabe des zwischen den Klammern stehenden Befehls.

z.B.:

echo bli $(echo bla) blo

...würde "bli bla blo" ausgeben. Nicht sehr sinnvoll, aber demonstriert wie das Ganze funktioniert:

Die Shell führt zuerst "echo bla" aus, das Ergebnis ist "bla" das wird zwischen "bli" und "blo" eingesetzt d.h. es wird dann der Befehl:

echo bli bla blo

ausgeführt..

Statt des "$( )" kann man auch "` `" schreiben, also die verkehrten einfachen Anführungszeichen (backgrave). Das ist aber meiner Meinung nicht so gut lesbar. Ich bevorzuge die "$( )" Schreibweise. Manche ältere Shells kennen allerdings die "$( )" Schreibweise nicht. Will man also "portable-scripts" schreiben, die auch auf anderen Shells als der Bash funktionieren, so ist die "`" (back grave) Substition zu bevorzugen.

Wir haben also jetzt die Möglichkeit Befehle zu schreiben, die wiederum andere Befehle aufrufen..

Nagut; ein sinnvolleres Beispiel für die Verwendung?

Die Verwendungsmöglichkeiten sind natürlich endlos. Angenommen, du hast ein File in dem in jeder Zeile der Name eines wichtigen Files steht, dass du jeden Tag auf einen anderen Server kopieren willst und es sind viele Files und ausserdem willst sie nicht immer händisch eintippen.

Legen wir uns z.B. so ein File an:

echo *.txt arbeiten/*.{txt,gif,jpg,html} > wichtige.txt

scp $(cat wichtige.txt) backupserver.irgendwo.at:backup/

Dieser Befehle würde also jetzt alle im File "wichtige.txt" angegebenen Files kopieren.

Oder:

...du willst dir ein Shell-Skript mit dem Namen "tagebuch" schreiben, dass jedesmal wenn du es aufrufst, den "joe" startet mit folgendem File:

/home/maxmeier/tagebücher/tagebuch2001.txt

An das Ende dieses Files soll dir automatisch das Jahr geschrieben werden. Das Scirpt könnte also so aussehn:

#!/bin/bash
TBUCH=$HOME/tagebücher/tagebuch$(date +%Y).txt
echo >> $TBUCH
echo log buch eintrag auf $(hostname) für $USER am $(date) >> $TBUCH
joe +99999999 $TBUCH
echo >> $TBUCH
echo ================================================== >> $TBUCH
echo >> $TBUCH


Was tut dieses Script?

Die erste Zeile: "#!/bin/bash" sagt, dass es ein Bash-Script ist. Die zweite Zeile setzt die Variable "TBUCH", dabei wird das aktuelle Jahr eingesetzt (der Befehl "date +%Y" gibt nur das Jahr aus) und das Jahr wird dort an der Stelle eingefügt. "$HOME" wird durch das Homeverzeichnis ersetzt.

Der Wert der Variablen "TBUCH" wäre also an dieser Stelle z.B.:

/home/maxmeier/tagebücher/tagebuch2001.txt

Die nächste Zeile hängt an dieses File eine Leerzeile an. ( ein ">" alleine, würde die Datei überschreiben. Zwei ">>" bedeuten, dass die Ausgabe des Befehls anfügt werden soll).

Die folgende Zeile fügt den Text:

log buch eintrag auf deincomputername für maxmeier am Mon Dec 10 13:04:36 MET 2001

ein. (Der Befehl "hostname" gibt immer den aktuellen Namen deines Computers aus. "$USER" ist dein Username und der Befehl "date -R" gibt das aktuelle Datum aus).

Danach wird "joe" aufgerufen. Mit "+123" würde er beim Starten an die Zeile 123 springen. Da wir aber eine so grosse Zahl angegeben haben springt "joe" immer gleich ans Ende. Dort wollen wir ja unseren Tagebuch-Text anfügen.

Nach dem Beenden von "joe" werden dann noch zwei Leerzeilen und eine Linie mit "=" Zeichen angefügt.

Um das Script zu testen würdest du es also in ein File mit dem Namen "tagebuch" speichern und es ausfürbar machen:

chmod ugo+rx tagebuch

Dann könntest du es mit:

./tagebuch

anstarten..

(Vorher aber noch

mkdir tagebücher

nicht vergessen)


EXERCISES:

* Versuche einer Environment-Variablen den aktuellen Wert der seit 1.1.1970 vergangenen Sekunden zuzuweisen.

( date +%s könnte hierfür nüztlich sein. Siehe dazu auch die "man"-Page von "date" )

* Gib mit "echo" den Wert aus.

* in einem File namens "wichtig.txt" steht in jeder Zeile der Name eines Verzeichnisses, das mit "tar" gebackupt werden soll. Wie könnte man mit "command subsitution" den "tar"-Befehl aufrufen, sodass er genau diese Verzeichnisse backupt?


REFERENCES:

man bash

(nach "command substitution" suchen)