eval bewertet seine Kommandozeilen-Argumente, als wären diese Eingabe für die Shell, d.h., Variablen werden ersetzt, und Kommandos werden ausgeführt.
Im ersten Beispiel hat daher y den Wert 7:

isolde bernd 3 sh
\h \W \! PS1='$ '
$ x='$y'
$ y=z
$ z=66
$ eval eval $x=7
$ echo x=$x y=$y z=$z
x=$y y=z z=7
$

Die Shell liest die Zeile

$ eval eval $x=7

und bewertet $x. Ausgeführt wird daher

$ eval eval $y=7

Das vordere eval bekommt als Kommandozeilen-Argumente eval und $y=7. Es bewertet diese Eingabe neu, d.h., es ersetzt $y durch den Wert der Variablen y, nämlich z, und führt dann den Befehl

eval z=7

aus. Dieses eval setzt dann z auf 7.

isolde Loesung 24 sh
\h \W \! PS1='$ '
$ x='$y'
$ y=z
$ z=666
$ eval echo $x=7
z=7
$



Das zweite Beispiel ist eine Endlosschleife. In der bash sieht man, daß schon nach kurzer Zeit die Prozeßtabelle überläuft.

isolde bernd 1 a=
isolde bernd 2 a='eval `$a`'
isolde bernd 3 $a
bash: fork: No more processes
isolde bernd 4

Die Eingabezeile $a wird von der Shell zu eval `$a` ersetzt und ausgeführt. Das eval führt aufgrund der Rückwärtshochkommata den Inhalt der Variablen a aus. Daher wird erneut eval gestartet usw.

Alle Kommandos mit einem s-Bit können nicht builtin sein, da sonst die Shell ein s-Bit haben müßte. Damit wäre aber jeder super-user. Beispiele dafür sind su, lpr, passwd und login.
Auf jeden Fall builtin müssen Kommandos wie trap, cd, ., continue, break, alle Kontrollstrukturen, exec, exit, export, read, readonly, set, shift und type sein.



trap definiert das Verhalten der Shell bei Eintreffen eines Signals.

trap "echo hi" 2
Ausgabe des Textes hi bei Eintreffen von Signal Nummer 2.

trap "echo hi" 0
Ausgabe des Textes hi bei Beenden der aktuellen Shell.

trap "" 2
Ignorieren vom Signal mit der Nummer 2.

trap ":" 2
Nichts machen beim Eintreffen vom Signal 2.

trap 2
Signalhandling für Signal 2 auf den defaul-Wert setzen.

trap
Gibt alle Signalnummern aus, für die nicht das default-Handling eingestellt ist.

Das Shell-Skript testTrap erzeugt ein Skript testTrap.sh, welches alle Signale abfängt und bei Eintreffen der Signale die Signalnummer auf der Standardausgabe ausgibt.

Trifft ein Signal mit der Nummer 2 bei Skript 1 während des sleeps ein, so terminiert das Skript. Skript 2 ignoriert dagegen das Signal.




±a:
Bei -a werden alle neu erzeugten oder geänderten Variablen automatisch exportiert.
Die Option +a schaltet diesen Zustand aus.

$ cat printA
#!/bin/sh
echo \$A=$A
exit 0
$ A="Hello World!"
$ echo $-
s
$ printA
$A=
$ set -a
$ echo $-
sa
$ A="Hello World!"
$ printA
$A=Hello World!

±n:
Die Option -n veranlaßt die Shell Befehle zu lesen, diese aber nicht auszuführen. Eine Eingabe von set +n ist danach nicht mehr möglich!

isolde Loesung 222 sh
\h \W \! PS1='$ '
$ set -n
$ ls
$ echo hi
$ exit
$ exit
$ exit
$ isolde Loesung 223

Damit kann man Shell-Skripte - ohne sie auszuführen - auf syntaktische Korrektheit prüfen.


±v:
Durch die Flagge -v wird die Shell in den verbose-Modus versetzt, d.h, sie gibt die Eingabezeile noch einmal aus. Die Option +v schaltet diesen Modus wieder ab.

isolde Loesung 234 sh
\h \W \! PS1='$ '
$ set -v
$ echo $HOME
echo $HOME
/home/bernd
$ echo $-
echo $-
vs
$

±x:
Durch die Flagge -x gibt die Shell jedes Kommando unmittelbar vor Ausführung aus. Die Option +x schaltet diesen Modus wieder ab.

$ set -x
$ echo $-
+ echo xs
xs
$ echo $HOME
+ echo /home/bernd
/home/bernd
$

±f:
Die Option f schaltet die Expansion von Mustern für Dateinamen an und aus:

$ set -f
$ echo * $-
* sf
$ set +f
$ echo ma? $-
ma? s
$ echo ma* $-
makeArchive makefile s

±t:
Durch -t wird die Shell veranlaßt nur einen Befel auszuführen und dann zu terminieren.

isolde bernd 6 sh
\h \W \! PS1='$ '
$ cat x
echo erste Zeile
echo zweite Zeile
$ sh -t x
erste Zeile

Das Shell-Skript makeArchive  erzeugt aus mehreren Dateien ein Archiv mit dem gewünschten Format. Zum Restaurieren der Dateien dient extractArchive .