blog · git · desktop · images · contact
2010-10-04
Ich habe hier gerade den Fall, dass ich in einem Shellskript testen
muss, ob stdout
ein Terminal ist oder nicht. Hintergrund ist: Ich will
bestimmte Kontrollsequenzen an XTerm senden. Das soll natürlich nur
passieren, wenn die Ausgabe auch an einem XTerm landet und nicht in
einer Pipe oder Datei -- die Sequenzen gehören auch unmittelbar zur
Ausgabe und dürfen nicht einfach über /dev/tty
an Umleitungen
"vorbeigeschmuggelt" werden.
Was eigentlich passieren muss, ist ein Aufruf von
isatty(1)
. Da ich nun eine halbe
Stunde an der falschen Stelle gesucht hatte, kam ich zuerst hierauf:
#include <unistd.h>
#include <stdlib.h>
int main(int argc, const char *argv[])
{
if (argc < 2)
return 1;
return !isatty(atoi(argv[1]));
}
Das funktioniert auch und man könnte es sich als isatty
in ~/bin
ablegen oder ähnlich. Dann würde "~/bin/isatty 1
" prüfen, ob stdout
ein Terminal ist. Anhand des Exit-Codes könnte man im Skript
entsprechend fortfahren.
In einem C-Programm ist das in Ordnung, aber natürlich für ein
Shellskript viel zu umständlich. Der "Königsweg" verbirgt sich hinter
dem test
-Befehl. Es ist nämlich -- wie immer -- eigentlich ganz
einfach und die Bash-Lösung sieht so aus:
#!/bin/bash
if [[ -t 1 ]]
then
echo "stdout ist ein TTY."
else
echo "stdout ist kein TTY."
fi
Die 1 in [[ -t 1 ]]
bezieht sich auf stdout
. Das könnte man auch mit
0 für stdin
, 2 für stderr
oder einem beliebigen anderen Deskriptor
machen. Für einzelne Aufrufe kann man sich das if
-Konstrukt sparen und
folgendes würde den "Auto Wraparound"-Modus beim XTerm abschalten, aber
eben nur, wenn es auch ein XTerm ist:
[[ "$TERM" == xterm* ]] && [[ -t 1 ]] && echo -n $'\e[?7l'
Übrigens: Selbst dann, wenn die Kontrollsequenzen, die ich brauche, in
der Terminfo-Datenbank enthalten wären und ich
tput
nutzen würde, käme ich nicht
um diesen Test herum. tput
sendet seine Codes unabhängig davon, was
auf der Gegenseite sitzt. Das kann man leicht mit einem
$ (tput setaf 1; echo hi) > /tmp/foo
$ xxd foo
0000000: 1b5b 3331 6d68 690a .[31mhi.
nachvollziehen. Wie man sieht, ist der Farbcode hier enthalten.