Why not use > file?
> mispipe
In bash there's PIPESTATUS for that.
Why not use > file?
> mispipe
In bash there's PIPESTATUS for that.
Sponge lets you do a series of piped transformations on 1 or more files and overwrite the result back to the original files.
Using > things will just break.
I’m guessing this also means you can’t pipe something bigger than what your memory can hold.
This, I learned the hard way, and I am not the only one. So in order for you not to make that mistake: the first thing that happens is that "file" is truncated, that happens before any command is run, so
sed s/foo/bar/ file > file
will always result in an empty "file", because it will be truncated before "sed" is run. I lost a couple of hours of work like that, once, and then I learned.From the manpage of sponge
sponge reads standard input and writes it out to the specified file. Unlike a shell redirect, sponge soaks up all its input before opening the output file. This allows constricting pipelines that read from and write to the same file.
So, the command sed s/foo/bar/ file | sponge file
will do what you expect sed s/foo/bar/ -i file
to edit file.This, btw, is why I hate shell scripts. There are so many variants of bourne shells and UNIX tools that writing a portable script is a minefield, as if properly dealing with spaces wasn't tricky enough...
There's a good Stack Overflow answer here: https://unix.stackexchange.com/questions/207919/sponge-from-...
I'm assuming sponge buffers everything in memory so you don't get concurrent modification bugs.
$ cat test
moo
$ cat < test > test
$ cat test
$ $ cat test
moo
$ cat < test | tee test > /dev/null
$ cat test
moo
...seems to work. Am I just getting lucky with a race condition? $ seq 1 99999 > f.txt
$ cat < f.txt | tee f.txt > /dev/null
$ wc -l f.txt
23696 f.txProbably this is buffering, either from dd or from the kernel.
$ dd if=/dev/urandom bs=1M count=1 of=test.bin 2>/dev/null
$ cp test.bin test2.bin
$ cat < test2.bin | tee test2.bin >/dev/null
$ diff test.bin test2.bin
Binary files test.bin and test2.bin differ
$ wc -c test{2,}.bin
131072 test2.bin
1048576 test.bin
Notice the file got truncated at exactly 128k; a nice round size for a write cache. tac | tac
is a safe bet since must be reading all file before by definition.