Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. It's 100% free, no registration required.

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

In the bash tutorial I am reading, it says that if you open a file descriptor for reading, i.e.

exec 3< echolist

Then you must close it like this,

exec 3<&-

However, if you open a file descriptor for writing, it must be closed like this:

exec 3>&-

Yet when I look on the internet, I see people opening files and then closing them with this:

exec 3>&- 

NOTE: when, according to the tutorial, they should be using exec 3<&1.

So my question is, can all file descriptors be closed via exec n>&- where n is the file descriptor number? Regardless if it was opened for reading, writing, or both?

share|improve this question
5  
The only difference between >&- and <&- is the default fd when not specified (>&- is 1>&- while <&- is 0<&-). Same for x>&y which is the same as x<&y except when x is not provided. – Stéphane Chazelas May 24 '14 at 17:01
up vote 21 down vote accepted

You can close file descriptor using both <&- and >&-, bash will parse two syntax as the same.

From file y.tab.c in bash source code:

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);
share|improve this answer
    
This can be used on <> file descriptors too. – CMCDragonkai Feb 17 at 4:42
    
No that's not possible, but as in 3>&- or 3<&- appears to close the descriptor. – CMCDragonkai Feb 17 at 9:01
    
<> is a read/write file descriptor, allowing one to read and write to the descriptor. – CMCDragonkai Feb 17 at 9:35
    
@CMCDragonkai: I know! But what do you mean This can be used on <> file descriptors too? – cuonglm Feb 17 at 9:44
    
That closing <> can be done via the same ways. – CMCDragonkai Feb 17 at 11:01

As far as I can see, exec 3>&- and exec 3<&- are the same and can be used on any file descriptor, regardless of how it was opened. According to sections 2.7.6 and 2.7.5 of the POSIX definition of the Shell Command Language:

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.

Note that neither specifies anything about how file descriptor n was opened originally. This is in line with the fact that close(2) doesn't care about how you opened the file.

A quick strace of the following:

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

versus this:

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

shows that in both cases, Bash does exactly the same thing.

Two Mildly Interesting Facts

  • The bash man page section on duplicating file descriptors does not mention that [n]>&- closes file descriptors.
  • In the Bash code for handling redirects (redir.c) you can find this:

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

An example for cuonglm's understanding of closing a '<>' FD.

This is quoted from the Advanced Bash-Scripting Guide at 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.
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.