[gelöst] Wie feststellen, ob stdin leer ist oder nicht? (bash)

Vom einfachen Programm zum fertigen Debian-Paket, Fragen rund um Programmiersprachen, Scripting und Lizenzierung.
Antworten
Benutzeravatar
MartinV
Beiträge: 459
Registriert: 31.07.2015 19:38:52

[gelöst] Wie feststellen, ob stdin leer ist oder nicht? (bash)

Beitrag von MartinV » 28.08.2017 13:10:50

Hallo!

Wie kann ich feststellen, ob in stdin Daten liegen oder nicht?
Mein Problem mit tools wie cat:

Code: Alles auswählen

echo foo | cat > datei 
ergibt die Ausgabe foo bzw. schreibt foo in datei.
Aber wenn cat keinen Input von stdin bekommt, wartet es für immer, und mein Skript geht nicht weiter:

Code: Alles auswählen

cat > datei    # cat wartet 100 Jahre auf Input von stdin
Ich habe einen etwas häßlichen workaround: Ich lese ein Byte mit read (und timeout 0.1 Sekunden), und falls es ein Byte gibt, rufe ich cat auf.

Code: Alles auswählen

IFS="" read -t 0.1 -rn 1 Byte
[ -n "$Byte" ] && {
  echo -n $Byte
  cat
} > datei
Ein anderer workaround:

Code: Alles auswählen

cat <(cat) > datei
Wenn stdin leer ist, bricht <(cat) meistens mit einem I/O-Fehler ab, und das Skript geht weiter. Ich habe aber auch Situationen gehabt, wo cat nicht abbrach (müßte ich noch einmal nachstellen, was die genauen Umstände sind).

Als Hintergrundprozeß bekommt cat gar keine Daten, auch wenn es welche in stdin gibt:

Code: Alles auswählen

cat > datei &
Es gibt noch "ifne", um stdin zu überprüfen. Es ist jedoch kein Bestandteil der coreutils und muß erst nachinstalliert werden (Debianmoreutils). Auf diese Abhängigkeit will ich nicht angewiesen sein. (Edit: Ein Test ergab, daß ifne genauso festhängt wie cat).
Ein simples [ -s /dev/stdin ] funktioniert leider auch nicht.

Ein paar Threads, in denen ich keine zufriedenstellende Lösung gefunden habe:
https://superuser.com/questions/210054/ ... pty-return
https://unix.stackexchange.com/question ... if-it-isnt

Gibt es eine saubere Lösung?
Zuletzt geändert von MartinV am 28.08.2017 20:25:12, insgesamt 1-mal geändert.
Die Vernunft kann einem schon leidtun. Sie verliert eigentlich immer.

scientific
Beiträge: 2922
Registriert: 03.11.2009 13:45:23
Lizenz eigener Beiträge: Artistic Lizenz
Kontaktdaten:

Re: Wie feststellen, ob stdin leer ist oder nicht? (bash)

Beitrag von scientific » 28.08.2017 18:32:43

Was ist mit

Code: Alles auswählen

 echo foo > datei
?
dann putze ich hier mal nur...

Eine Auswahl meiner Skripte und systemd-units.
https://github.com/xundeenergie

auch als Debian-Repo für Testing einbindbar:
deb http://debian.xundeenergie.at/xundeenergie testing main

Benutzeravatar
inne
Beiträge: 1892
Registriert: 25.06.2013 15:45:12
Lizenz eigener Beiträge: GNU General Public License
Kontaktdaten:

Re: Wie feststellen, ob stdin leer ist oder nicht? (bash)

Beitrag von inne » 28.08.2017 19:14:34

Hallo,
irgendwo im Forum ist das beantwortet:

Code: Alles auswählen

#!/bin/bash
if [[ ! -t 0 ]]; then
	cat
else
	:
fi
(=_=)

You guys do what you do best... find something simple and complicate it!

Benutzeravatar
MartinV
Beiträge: 459
Registriert: 31.07.2015 19:38:52

Re: Wie feststellen, ob stdin leer ist oder nicht? (bash)

Beitrag von MartinV » 28.08.2017 20:22:27

inne hat geschrieben: ↑ zum Beitrag ↑
28.08.2017 19:14:34

Code: Alles auswählen

#!/bin/bash
if [[ ! -t 0 ]]; then
	cat
else
	:
fi
Cool! Das funktioniert! :D
Ich habe es reduziert auf:

Code: Alles auswählen

[ -t 0 ] || cat > datei
Ich vermute, Deine Schreibweise ist allgemeingültiger, auch für andere Shells? (Ich bin mit den doppelten [[ ]] nicht vertraut.)
scientific hat geschrieben: ↑ zum Beitrag ↑
28.08.2017 18:32:43
Was ist mit

Code: Alles auswählen

 echo foo > datei
?
Vielleicht habe ich es in der Frage nicht deutlich gemacht: Ich habe ein Skript, das mit oder ohne Input von stdin aufgerufen werden kann. Ich darf "cat > datei" aber nur im Skript ausführen, wenn es auch tatsächlich Daten zu lesen gibt. Wenn stdin leer ist, wartet cat für immer, und mein Skript hängt fest.

Danke!
Die Vernunft kann einem schon leidtun. Sie verliert eigentlich immer.

Antworten