#23: File descriptors

Posted by | Comments (0) | Trackbacks (3)

File descriptors are very essential in programming. When you open a file, you get a token, which identifies the file instance. With this token you refer to the file, write, read or close it. You have about the same on the shell.

There are three default file descriptors:

  1. Standard input (STDIN)
  2. Standard output (STDOUT)
  3. Standard error (STDERR)

They are numbered from 0 to 2 and you can handle them with the input and output redirection operators < and >:

# Redirect STDIN
cmd <file

# Redirect stdout
cmd > file

Without any number, < uses STDIN and > STDOUT, but you can also change this behavior:

cmd 2> file

That would redirect STDERR to the file file. You can also append STDERR to STDOUT and redirect both at the same time:

cmd > file 3>&1

That's very basic and you should already know that. But there's more than just this. Besides 1, 2 and 3, there are also file descriptors 3 to 1023, which are free to use. For each one a symlink in /dev/fd/ is created as soon as they are initialized.

To use these, you have to know the exec command. This command can create, move and close file descriptors of the current process as well as replacing the shell. So to replace the currently running bash shell with a zsh, run

exec zsh

You can also specify any other command, but that would normally log you out of your shell.

But more important is the handling of custom file descriptors. To create a read/write file descriptor for a file run:

exec 3<> file

That creates a file descriptor with the number 3. You could also create a read-only or write-only file descriptor by just specifying < or >, respectively, but note that the file must already exist for read-only descriptors. Now write to this file:

# Open file and assign descriptor
exec 3<> file

# Write to file
echo 'foobar' >&3

# Reopen file to reset pointer
exec 3<> file

# Read from file
<&3 cat

This would first write foobar to the file and then read the written string. Note that reopening the file is necessary here because the write process has set the file pointer past the last line, so the read command would read an empty string.

You can close a file descriptor with n<&- for input file descriptors and n>&- for output file descriptors. For instance

3>&-

to close the file descriptor 3.

It is also possible to copy file descriptors. This is important if you want to reassign STDOUT or STDIN. If you don't clone the file descriptor first, you wouldn't be able to restore it afterwards.

# Backup STDOUT to fd 3
exec 3>&1

# Redirect all STDOUT to file
exec >file

# Should now go to file
echo 'test'

# Restore STDOUT and close fd 3
exec >&3 3>&-

You can do the same with STDIN. Of course, you can also close STDIN and STDOUT. If you do that, you'll get an error message as soon as you try to access one of these channels.

Read more about file descriptors and exec:

Trackbacks

robo47 sent a Trackback on : (permalink)

RT @reflinux: #Advent series "24 Short #Linux #Hints", day 23: File descriptors http://bit.ly/i4urUq

Manko10 sent a Trackback on : (permalink)

RT @reflinux: #Advent series "24 Short #Linux #Hints", day 23: File descriptors http://bit.ly/i4urUq

Comments

No comments have been submitted yet. Be the first!

Write a comment:

E-Mail addresses will not be displayed and will only be used for E-Mail notifications.

By submitting a comment, you agree to our privacy policy.

Design and Code Copyright © 2010-2025 Janek Bevendorff Content on this site is published under the terms of the GNU Free Documentation License (GFDL). You may redistribute content only in compliance with these terms.