Warum ergeben sich diese beiden 'cat'-Befehle unterschiedlich?

12

Nehmen wir an, dass infile einen bestimmten Text enthält und ich die folgenden Befehle ausführen sollte:

exec 3<infile

cat-n <&3

cat-n <&3

Die erste Instanz von cat zeigt den Inhalt der Datei an, aber das zweite Mal scheint nichts zu tun. Warum unterscheiden sie sich?

Nicht-Terrorist
quelle

Antworten:

29

Sie sehen aus wie derselbe Befehl, unterscheiden sich jedoch dadurch, dass sich der Systemstatus infolge des ersten Befehls geändert hat. Insbesondere hat der erste catdie gesamte Datei konsumiert, so dass der zweite catnichts mehr zu lesen hat, sofort EOF (Dateiende) erreicht und beendet.

Der Grund dafür ist, dass Sie für beide Aufrufe von genau dieselbe Dateibeschreibung verwenden (die, die Sie mit exec < infiledem Dateideskriptor erstellt und diesem zugewiesen haben 3) cat. Eines der Dinge, die mit einer offenen Dateibeschreibung verbunden sind, ist ein Dateiversatz. Der erste catliest also die gesamte Datei, belässt den Versatz am Ende und der zweite versucht, vom Ende der Datei aufzugreifen und findet nichts zu lesen.

jw013
quelle
12

Nur um die gute Antwort von @ jw013 zu ergänzen, kann es hilfreich sein zu erkennen, dass es dasselbe ist wie

{
   cat -n
   cat -n
} < infile

< fileDa es sich um eine Abkürzung 0< filehandelt, wird anstelle von 3 der Dateideskriptor 0 verwendet.

Und um die Sache ein wenig zu verwirren, diese Version:

exec 3< infile
cat -n /dev/fd/3
cat -n /dev/fd/3

Anders verhält sich je nach Betriebssystem Sie es in und laufen Art von infile(reguläre Datei vs Rohr vs Gerät ...)

Unter Solaris und die meisten kommerziellen Unix - Varianten, ein open("/dev/fd/3")mehr oder weniger gleichbedeutend mit einem dup(3)(so < /dev/fd/3ist etwa die gleiche wie <&3), während auf Linux, für reguläre Dateien, /dev/fd/3als symbolischen Link auf die Originaldatei implementiert ist, so open("/dev/fd/3")es erneut von Anfang an geöffnet ( und evtl. mit abweichenden fahnen vom fd 3).

Stéphane Chazelas
quelle