Fermer un descripteur de fichier,> & - vs <& -

49

Dans le tutoriel bash que je lis, il est dit que si vous ouvrez un descripteur de fichier pour la lecture, c'est-à-dire

exec 3< echolist

Ensuite, vous devez le fermer comme ça,

exec 3<&-

Cependant, si vous ouvrez un descripteur de fichier en écriture, vous devez le fermer comme suit:

exec 3>&-

Pourtant, lorsque je regarde sur Internet, je vois des gens ouvrir des fichiers puis les fermer avec ceci:

exec 3>&- 

NOTE: quand, selon le tutoriel, ils devraient utiliser exec 3<&1.

Ma question est donc la suivante: tous les descripteurs de fichier peuvent-ils être fermés via exec n>&-où n est le numéro du descripteur de fichier? Peu importe s'il était ouvert à la lecture, à l'écriture ou aux deux?

Jason
la source
21
La seule différence entre >&-et <&-est le fd par défaut lorsqu'il n'est pas spécifié ( >&-est 1>&-while <&-est 0<&-). Identique pour x>&yce qui est identique à x<&ysauf que si xnon fourni.
Stéphane Chazelas

Réponses:

48

Vous pouvez fermer le descripteur de fichier en utilisant à la fois <&-et >&-, bashanalysera la même syntaxe.

Du fichier y.tab.c dans bashle code source:

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
la source
2
Cela peut aussi être utilisé sur <>les descripteurs de fichiers.
CMCDragonkai
1
Non, ce n'est pas possible, mais comme dans 3>&-ou 3<&-semble fermer le descripteur.
CMCDragonkai
1
Cette fermeture <>peut se faire de la même manière.
CMCDragonkai
1
Je ne peux pas comprendre ce que tu veux dire. S'il vous plaît donner un exemple./
cuonglm
1
Je ne pense pas que c'est ce que je voulais dire. Seulement, un descripteur de fichier en lecture-écriture peut être fermé en utilisant 3> & - et 3 <& -.
CMCDragonkai
15

Pour autant que je peux voir, exec 3>&-et exec 3<&-sont les mêmes et peut être utilisé sur un descripteur de fichier, quelle que soit la façon dont il a été ouvert. Selon les sections 2.7.6 et 2.7.5 de la définition POSIX du langage de commande Shell :

2.7.5 Dupliquer un descripteur de fichier d'entrée

L'opérateur de redirection:

[n] <& word

[...COUPER...]

Si le mot est évalué à '-', le descripteur de fichier n ou l'entrée standard si n n'est pas spécifié, doit être fermé. Les tentatives de fermeture d’un descripteur de fichier qui n’est pas ouvert ne constituent pas une erreur. Si word est évalué à autre chose, le comportement n'est pas spécifié.

2.7.6 Dupliquer un descripteur de fichier de sortie

L'opérateur de redirection:

[n]> & word

[...COUPER...]

Si le mot est évalué à '-', le descripteur de fichier n ou la sortie standard si n n'est pas spécifié est fermé. Les tentatives de fermeture d’un descripteur de fichier qui n’est pas ouvert ne constituent pas une erreur. Si word est évalué à autre chose, le comportement n'est pas spécifié.

Notez que ni l'un ni l'autre ne spécifie quoi que ce soit sur la façon dont le descripteur de fichier n a été ouvert à l'origine. Ceci est conforme au fait que close (2) ne se soucie pas de la façon dont vous avez ouvert le fichier.

Un bref aperçu de ce qui suit:

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

par rapport à ceci:

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

montre que dans les deux cas, Bash fait exactement la même chose.

Deux faits légèrement intéressants

Steven D
la source
1
La page de manuel bash mentionne la fermeture, citant votre lien: Si le mot est évalué à '-', le descripteur de fichier n est fermé.
studog
@studog Merci d'avoir vérifié la source! Je pense que ce qui est arrivé ici est que je cherchais une page de manuel locale pour Bash 3, puis un lien vers la documentation en ligne, qui était pour Bash 4. Dans l'ancienne documentation de Bash 3, la phrase sur la fermeture était omise de la description de [N]>&WORD: git .savannah.gnu.org / cgit / bash.git / tree / doc /…
Steven D
7

Un exemple pour la compréhension par Cuonglm de la fermeture d’un FD <<>.

Ceci est cité dans Advanced Bash-Scripting Guide, à l' adresse http://tldp.org/LDP/abs/html/io-redirection.html.

[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
la source