Sometimes we want to process a file and write back to the same file (aka in-place editing). However, the simplest shell redirection won’t do the job:

cat a.txt > a.txt           # doesn't work

This effectively truncates a.txt.

With sponge

We can use sponge (included in moreutils) for this kind of work:

cat a.txt | sponge a.txt

This works because sponge soaks up all input before writing the output file.

Without sponge

What if we don’t have sponge?

We can output to a temporary file and then rename it to the original file:

cat a.txt > b.txt
mv b.txt a.txt

In fact we can do it a little fancier:

{ rm a.txt && cat > a.txt ; } < a.txt

Or even more (if the command doesn’t read from stdin):

{ rm a.txt && cat <(cat) > a.txt ; } < a.txt