🎓 A1Learner
🔍
0 of 45 lessons completed

Bash Closing File Descriptors

Closing file descriptors is the act of releasing a numbered channel once its work is done. A closed number is free for reuse, and a closed input stops feeding a reader.

A closed number is reused by the next open

Descriptor 3 is opened on one file, closed, then opened on a second file. Both files hold their own line, so the reuse worked.

exec 3>first.txt
echo "first file" >&3
exec 3>&-
exec 3>second.txt
echo "second file" >&3
exec 3>&-
cat first.txt
cat second.txt

Restore stdout before closing the saved copy

Stdout is saved on descriptor 3, then redirected to a file. Restoring stdout first puts later output back on screen, and closing the copy last keeps the order safe.

exec 3>&1
exec 1>saved.txt
echo "saved line"
exec 1>&3
exec 3>&-
echo "back on screen"
cat saved.txt

Close an input descriptor after its loop

The loop reads every line through descriptor 3. Closing it after the loop marks the input as finished.

printf 'one\ntwo\n' > items.txt
exec 3<items.txt
while read -u 3 line; do
  echo "got: $line"
done
exec 3<&-
echo "input closed"

Example

exec 3>part-one.txt
echo "part one" >&3
exec 3>&-
exec 3>part-two.txt
echo "part two" >&3
exec 3>&-
echo "both parts written"
cat part-one.txt
cat part-two.txt

Key points

  • Close syntax: use >&- for an output descriptor and <&- for an input descriptor.
  • Free numbers: closing frees the number, so a later open can reuse it.
  • Close after use: close a descriptor only after its last read or write.
  • Restore before closing: restore a saved descriptor before closing its copy, or the saved copy is lost.
  • Never close blindly: closing 0, 1, or 2 breaks normal input and output for the rest of the script.
  • Close at the end: a loop that reads from a descriptor should close it once the loop finishes.

In this example, descriptor 3 is opened on the first part file and closed after its line is written. The same number is then opened on the second part file and closed after its line. The final lines show both parts, so the close-and-reuse sequence worked.

Try it Yourself

Edit the code, then press Run.

Running is simulated

Exercise

What happens when a descriptor is closed and then opened again?