Echo to file descriptor overwrites the file?
Because you hadn't done any reads on descriptor 88, the current seek position was "0", and so the write took place at that point.
If, instead, you'd read the file before then, then appends happen:
bash-4.2$ cat <&88
The quick brown fox ...
The quick brown fox ...
bash-4.2$ echo hello >&88
bash-4.2$ cat example.txt
The quick brown fox ...
The quick brown fox ...
hello
bash-4.2$ echo more >&88
bash-4.2$ cat example.txt
The quick brown fox ...
The quick brown fox ...
hello
more
As @Zoonose correctly points out, each filedescriptor has its own read-write cursor position within the file that it's connected to. And a file can be opened either by the shell when you use a redirection such as <>
, or by a program such as cat
.
But the numbers that you think of as "a filedescriptor" are just references to the actual filedescriptors within the kernel, and it's entirely normal for one filedescriptor to have multiple such reference numberss, either within a single process, or between processes.
So when you open a terminal window (or log in by ssh), you start with a single filedescriptor open to your terminal, connected as fd#0, fd#1 & fd#2 in your shell process. Any process that the shell starts with inherit these by default -- except where you've used pipes or redirections.
The redirection >>
flags the filedescriptor as O_APPEND
, so that writes through that filedescriptor ignore the cursor and go onto the end of the file.
The redirection >
causes the target file to be truncated just once, before any writing is done. Thus any writing after that normally goes into the empty space past the end of the file.
Writes to a file do not themselves cause truncation; they will simply replace whatever is at the current position, and stretch the end-of-file if necessary.
Note that somecmd >&88
will cause the stdout (fd#1) for somecmd to share the filedescriptor with fd#88 of the current shell. That means it will share the O_APPEND
option, if present. It won't cause it to be truncated again; that's a one-time thing.
What you're seeing in the case is that there's no truncation when you use >&88
, because fd#88 wasn't opened using >>
, and so writes from multiple processes can be interleaved.