Relentless Coding

A Developer’s Blog

Overwrite File Without Truncating

In Bash, when you open a file for writing, the file gets truncated. However, there is a way to open a file for both reading and writing at the same time.

Who hasn’t made the mistake of creating a process that tries to both read and write to the same file?

$ wc -c file
17 file
$ sed s/foo/FOO/ <file >file
$ wc -c file
0

Oops. That’s why for sed(1) in particular you use the -i[SUFFIX], --in-place[=SUFFIX] switch, and in general can use sponge(1) from moreutils (e.g. grep foo <file | sponge >file).

But you can also open a file for reading and writing, by using the [n]<>word syntax. This is described in bash(1) under “REDIRECTION” > “Opening File Descriptors for Reading and Writing”:

The redirection operator

    [n]<>word

causes the file whose name is the expansion of word to be opened for both reading and writing on file descriptor n, or on file descriptor 0 if n is not specified. If the file does not exist, it is created.

Test drive:

$ cd $(mktemp -d)
$ ls
$ cat > test
Hello, world!
^D
$ cat >> test
Another line
^D
$ cat 1<> test
G'day^D
$ cat test
G'day, world!
Another line