关闭文件描述符,>&-vs <&-


49

在我正在阅读的bash教程中,它说如果您打开文件描述符进行读取,即

exec 3< echolist

然后您必须像这样关闭它

exec 3<&-

但是,如果打开文件描述符进行写入,则必须像这样关闭它:

exec 3>&-

然而,当我在互联网上浏览时,我看到人们打开文件,然后用以下命令关闭文件:

exec 3>&- 

注意:根据教程,何时应使用exec 3<&1

所以我的问题是,是否可以通过exec n>&-n是文件描述符编号来关闭所有文件描述符?不管它是开放供阅读,写作还是同时开放?


21
之间的唯一区别>&-<&-是未指定时的默认FD(>&-1>&-同时<&-0<&-)。与未提供时x>&y相同,x<&y相同x
斯特凡Chazelas

Answers:


48

您可以使用<&-和来关闭文件描述符>&-bash将解析两个语法相同。

从源代码中的文件y.tab.cbash

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);

2
这也可以用于<>文件描述符。
CMCDragonkai '16

1
不行,这是不可能的,但因为3>&-3<&-似乎关闭了描述符。
CMCDragonkai '16

1
<>可以通过相同的方式完成关闭。
CMCDragonkai '16

1
我听不懂你的意思。请给一个example./
cuonglm

1
我认为那不是我的意思。只是可以使用3>&-和3 <&-关闭读写文件描述符。
CMCDragonkai

15

据我所看到的,exec 3>&-并且exec 3<&-是相同的,可以在任何文件描述符可以使用,不管它是如何打开。根据Shell命令语言的POSIX定义的第2.7.6和2.7.5节:

2.7.5复制输入文件描述符

重定向运算符:

[n] <&word

[... SNIP ...]

如果word评估为'-',则文件描述符n或未指定n的标准输入应关闭。尝试关闭未打开的文件描述符不会构成错误。如果单词评估为其他内容,则行为是不确定的。

2.7.6复制输出文件描述符

重定向运算符:

[n]>&word

[... SNIP ...]

如果word求值为'-',则关闭文件描述符n,如果未指定n,则关闭标准输出。尝试关闭未打开的文件描述符不会构成错误。如果单词评估为其他内容,则行为是不确定的。

请注意,它们都未指定有关文件描述符n最初如何打开方式的任何信息。这符合以下事实:close(2)并不关心您如何打开文件。

快速浏览以下内容:

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

与此:

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

表明在两种情况下,Bash都做同样的事情。

两个有趣的事实

  • 对复制文件描述符bash的手册页节没有提到[n]>&-关闭文件描述符。
  • 在用于处理重定向的Bash代码(redir.c)中,您可以找到以下代码:

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

1
bash手册页确实提到了关闭,并引用了您的链接:如果word评估为'-',则文件描述符n关闭。
studog

@studog感谢您检查源!我认为这里发生的是我正在查看Bash 3的本地手册页,然后链接到Bash 4的在线文档。在旧的Bash 3文档中,关于git的描述省略了[N]>&WORD.savannah.gnu.org / cgit / bash.git / tree / doc /…
Steven D

7

cuonglm了解关闭“ <>” FD的示例。

这是从http://tldp.org/LDP/abs/html/io-redirection.html的《高级Bash脚本指南》中引用的。

[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.
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.