Fechando um descritor de arquivo, & - vs & -

45

No tutorial do bash que estou lendo, ele diz que, se você abrir um descritor de arquivo para leitura, por exemplo,

exec 3< echolist

Então você deve fechá-lo assim,

exec 3<&-

No entanto, se você abrir um descritor de arquivo para gravação, ele deve ser fechado assim:

exec 3>&-

No entanto, quando vejo na internet, vejo pessoas abrindo arquivos e, em seguida, fechando-os com isso:

exec 3>&- 

NOTA: quando, de acordo com o tutorial, eles devem estar usando exec 3<&1 .

Então, minha pergunta é: todos os descritores de arquivo podem ser fechados via exec n>&- , onde n é o número do descritor de arquivo? Independentemente se foi aberto para leitura, escrita ou ambos?

    
por Jason 24.05.2014 / 15:49

3 respostas

45

Você pode fechar o descritor de arquivo usando <&- e >&- , bash analisará duas sintaxes iguais.

Do arquivo y.tab.c em bash código fonte:

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);
    
por 24.05.2014 / 20:23
13

Tanto quanto eu posso ver, exec 3>&- e exec 3<&- são os mesmos e podem ser usados em qualquer descritor de arquivo, independentemente de como ele foi aberto. De acordo com as seções 2.7.6 e 2.7.5 da definição POSIX da Linguagem de Comando Shell :

2.7.5 Duplicating an Input File Descriptor

The redirection operator:

[n]<&word

[...SNIP...]

If word evaluates to '-', file descriptor n, or standard input if n is not specified, shall be closed. Attempts to close a file descriptor that is not open shall not constitute an error. If word evaluates to something else, the behavior is unspecified.

2.7.6 Duplicating an Output File Descriptor

The redirection operator:

[n]>&word

[...SNIP...]

If word evaluates to '-', file descriptor n, or standard output if n is not specified, is closed. Attempts to close a file descriptor that is not open shall not constitute an error. If word evaluates to something else, the behavior is unspecified.

Observe que nem especifica nada sobre como o descritor de arquivo n foi aberto originalmente. Isso está de acordo com o fato de que close (2) não se importa com a forma como você abriu o arquivo.

Um rápido resumo do seguinte:

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

versus isso:

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

mostra que, em ambos os casos, o Bash faz exatamente a mesma coisa.

Dois fatos levemente interessantes

  • A seção bash man na duplicação de descritores de arquivos não mencionar que [n]>&- fecha descritores de arquivos.
  • No código Bash para lidar com redirecionamentos (redir.c) você pode encontrar isto:

    738      /* XXX - what to do with [N]<&$w- where w is unset or null?  ksh93
    739               closes N. */
    
por 24.05.2014 / 17:44
5

Um exemplo para a compreensão do cuonglm de fechar um '< >' FD.

Isso é citado no Guia avançado de script de script no link

[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.
    
por 22.02.2016 / 22:32