Spong 'soaks up' input an releases it all on one chunk so that you can do things like:
cat foo | sponge foo
(`cat foo > foo` does not work)That's neat and all, but what if you don't have sponge? Well, just use tac twice!
cat foo | tac | tac > foo
(Obviously this is rather wasteful ;))"cat foo > foo" breaks, because the shell truncates the file "foo" while it's setting up the redirection, before it launches "cat foo", and so cat has nothing to read.
"cat foo | sponge foo" works because the shell is not responsible for writing to foo; it launches cat (which opens the file for reading) then launches sponge (which eventually opens the file for writing).
I would thus expect "cat foo | tac | tac > foo" to fail in the same way as "cat foo > foo" because the shell is still going to open the file foo and truncate it, but experimentation shows that it does actually work. Is it because the shell launches each pipeline one at a time, so cat has read the file before "tac > foo" truncates it? Is it a race-condition or a corner-case?
Furthermore `cat foo | cat > foo` does not work, but `cat foo | cat | cat > foo` does work.
I suspect this behavior is actually a race condition of some sort.
Edit: definetly a race condition, shown by larger files:
% wc -l foo
1310720 foo
% cat foo | cat | cat > foo
% wc -l foo
16384 1