Schließen eines Dateideskriptors,> & - vs <& -

49

In dem Bash-Tutorial, das ich lese, heißt es, dass, wenn Sie einen Dateideskriptor zum Lesen öffnen, d. H

exec 3< echolist

Dann müssen Sie es so schließen,

exec 3<&-

Wenn Sie jedoch einen Dateideskriptor zum Schreiben öffnen, muss dieser folgendermaßen geschlossen werden:

exec 3>&-

Wenn ich jedoch im Internet nachschaue, sehe ich, wie Leute Dateien öffnen und dann mit diesen schließen:

exec 3>&- 

HINWEIS: Wenn sie laut Tutorial verwendet werden sollen exec 3<&1.

Meine Frage ist also, ob alle Dateideskriptoren geschlossen werden können, exec n>&-wobei n die Dateideskriptornummer ist. Egal, ob es zum Lesen, Schreiben oder für beides geöffnet wurde?

Jason
quelle
21
Der einzige Unterschied zwischen >&-und <&-ist der Standardwert fd, wenn nichts angegeben ist ( >&-is 1>&-while <&-is 0<&-). Das Gleiche gilt für x>&ydie gleiche ist , wie es x<&ysei denn, xnicht vorgesehen ist.
Stéphane Chazelas

Antworten:

48

Sie können mit Dateideskriptor schließen beide <&-und >&-, bashzwei Syntax wie die gleiche analysieren wird.

Aus der Datei y.tab.c im bashQuellcode:

5385   /* Hack <&- (close stdin) case.  Also <&N- (dup and close). */                
5386   if MBTEST(character == '-' && (last_read_token == LESS_AND || last_read_token == GREATER_AND))
5387     return (character);
cuonglm
quelle
2
Dies kann auch für <>Dateideskriptoren verwendet werden.
CMCDragonkai
1
Nein, das ist nicht möglich, aber wie in 3>&-oder 3<&-scheint der Deskriptor zu schließen.
CMCDragonkai
1
Das Schließen <>kann auf die gleiche Weise erfolgen.
CMCDragonkai
1
Ich kann nicht verstehen, was du meinst. Bitte geben Sie ein Beispiel./
cuonglm
1
Ich glaube nicht, dass ich das gemeint habe. Nur dass ein Lese- / Schreib-Dateideskriptor auch mit 3> & - und 3 <& - geschlossen werden kann.
CMCDragonkai
15

Soweit ich sehen kann, sind exec 3>&-und exec 3<&-die gleichen und können für jeden Dateideskriptor verwendet werden, unabhängig davon, wie er geöffnet wurde. Gemäß den Abschnitten 2.7.6 und 2.7.5 der POSIX-Definition der Shell Command Language :

2.7.5 Duplizieren eines Eingabedateideskriptors

Der Umleitungsoperator:

[n] <& word

[... SNIP ...]

Wenn das Wort '-' ergibt, muss der Dateideskriptor n oder die Standardeingabe ohne Angabe von n geschlossen werden. Versuche, einen nicht geöffneten Dateideskriptor zu schließen, stellen keinen Fehler dar. Wenn word einen anderen Wert ergibt, ist das Verhalten nicht spezifiziert.

2.7.6 Duplizieren eines Ausgabedateideskriptors

Der Umleitungsoperator:

[n]> & word

[... SNIP ...]

Wenn word als '-' ausgewertet wird, wird der Dateideskriptor n oder die Standardausgabe geschlossen, wenn n nicht angegeben ist. Versuche, einen nicht geöffneten Dateideskriptor zu schließen, stellen keinen Fehler dar. Wenn word einen anderen Wert ergibt, ist das Verhalten nicht spezifiziert.

Beachten Sie, dass keines davon etwas darüber angibt, wie der Dateideskriptor n ursprünglich geöffnet wurde. Dies steht im Einklang mit der Tatsache, dass es close (2) egal ist, wie Sie die Datei geöffnet haben.

Ein kurzer Überblick über Folgendes:

exec 3< /etc/passwd
exec 4> foo
exec 3<&-
exec 4<&-

gegenüber diesem:

exec 3< /etc/passwd
exec 4> foo
exec 3<&-
exec 4>&-

zeigt, dass Bash in beiden Fällen genau dasselbe tut.

Zwei leicht interessante Fakten

Steven D
quelle
1
Die Bash-Manpage erwähnt das Schließen unter Angabe Ihres Links: Wenn das Wort "-" ergibt, wird der Dateideskriptor n geschlossen.
Studog
@studog Danke, dass du die Quelle überprüft hast! Ich denke, was hier passiert ist, ist, dass ich eine lokale Manpage für Bash 3 angesehen und dann auf die Online-Dokumentation für Bash 4 verlinkt habe. In der alten Bash 3-Dokumentation wurde der Satz zum Schließen in der Beschreibung von [N]>&WORD: git
Steven D
7

Ein Beispiel für das Verständnis von cuonglm, ein '<>' FD zu schließen.

Dies wird aus dem Advanced Bash-Scripting Guide unter http://tldp.org/LDP/abs/html/io-redirection.html zitiert

[j]<>filename
  #  Open file "filename" for reading and writing,
  #+ and assign file descriptor "j" to it.
  #  If "filename" does not exist, create it.
  #  If file descriptor "j" is not specified, default to fd 0, stdin.
  #
  #  An application of this is writing at a specified place in a file. 
  echo 1234567890 > File    # Write string to "File".
  exec 3<> File             # Open "File" and assign fd 3 to it.
  read -n 4 <&3             # Read only 4 characters.
  echo -n . >&3             # Write a decimal point there.
  exec 3>&-                 # Close fd 3.
  cat File                  # ==> 1234.67890
  #  Random access, by golly.
DMW
quelle