2010-10-08 4 views
16

Wenn die Ausgabe eines Befehls in eine Datei umgeleitet wird, wird die Ausgabedatei von der Shell erstellt oder abgeschnitten, bevor der Befehl ausgeführt wird, irgendeine Idee, was cat foo> foo tut?In UNIX was "cat file1> file1 tut?"

+1

Ich vermute, dies wäre ein sehr guter Test für das Verhalten der Shell. –

Antwort

17

In allen Fällen wird die Datei abgeschnitten. Das liegt daran, dass die Umleitung von der Shell gehandhabt wird, die die Datei zum Schreiben vor dem Aufruf des Befehls öffnet.

cat foo > foo 

Die Verkürzungen Shell und öffnet foo zum Schreiben, setzt stdout in die Datei, und dann die exec ["cat", "foo"].

GNU Katze ist klug und weigert sich, eine Datei an sich selbst umzuleiten. Dazu überprüft er das Device/Inode-Paar auf den Deskriptoren der Eingabe- und Ausgabedatei. Sie können die wunderbaren Low-Level-Details in src/cat.c lesen. Es druckt eine Nachricht und wird beendet.

BSD Katze hat keine solche Sicherheit, aber da die Datei bereits abgeschnitten wurde, gibt es nichts zu lesen, nichts zu schreiben, und es wird anhalten.


Sie können die Dinge etwas aufpeppen, indem Sie sie anhängen und nicht abschneiden.

echo hello > foo 
cat foo >> foo 

Jetzt ist alles gleich, außer dass die Shell die Datei zum Anhängen öffnet, anstatt sie zu kürzen.

GNU Katze sieht, was Sie tun und stoppt; Die Datei ist unberührt.

BSD cat geht in eine Schleife und hängt die Datei an sich an, bis die Festplatte voll ist.

+0

Und deshalb ist Mac auf BSD gebaut. –

2

Die Datei wird zuerst abgeschnitten und dann gelesen, sodass dieser Befehl die Datei abschneidet.

Als ich versuchte, ihn auszuführen ich diese Warnung bekam:

Katze: test.txt: Eingabedatei Ausgabedatei

+0

Welche "Katze" hast du auf der Plattform? 'cat foo> foo' ergibt für mich eine leere' foo' Datei. – birryree

4

auf Fedora 13 das ist, was ich sehe,

cat foo > foo 
cat: foo: input file is output file 

Wenn foo etwas zuvor enthielt, ist es weg.

1

Shell wird gestutzt, cat offenbar prüft eine benannte Parm, aber nicht überprüfen gegen stdin wie unten und es gelingt ihm immer:

$ uname -a 
Linux bar 2.6.18-164.15.1.el5PAE #1 SMP Wed Mar 17 12:14:29 EDT 2010 i686 i686 i386 GNU/Linux 
$ dd if=/dev/urandom of=foo bs=1024 count=4 
4+0 records in 
4+0 records out 
4096 bytes (4.1 kB) copied, 0.00334456 seconds, 1.2 MB/s 
$ od -c foo |head -2 
0000000 U 371 003 z 224 334 z K 236 221 k  < c 256 ! 
0000020 % % 256 V \ 005 , 254 X 202 330 004 222 " 037 226 
$ cat <foo >foo && od -c foo 
0000000 
+0

Vielen Dank für Ihre Antworten. Sie waren alle hilfreich. – HelloWorld