19
> brew install moreutils                                                          
==> Downloading https://homebrew.bintray.com/bottles/moreutils-0.55.yosemite.bottle.tar.gz    
######################################################################## 100.0%               
==> Pouring moreutils0.55.yosemite.bottle.tar.gz       
🍺  /usr/local/Cellar/moreutils/0.55: 67 files, 740K   

sponge reads standard input and writes it out to the specified file. Unlike a shell redirect, sponge soaks up all its input before writing the output file. This allows constructing pipelines that read from and write to the same file.

I don't understand. Please give me some useful examples.

What does soaks up mean?

36

Assume that you have a file named input, you want to remove all line start with # in input. You can get all lines don't start with # using:

grep -v '^#' input

But how do you make changes to input? With standard POSIX toolchest, you need to use a temporary file, some thing like:

grep -v '^#' input >/tmp/input.tmp
mv /tmp/input.tmp ./input

With shell redirection:

grep -v '^#' input >input

will truncate input before you reading from it.

With sponge, you can:

grep -v '^#' input | sponge input
| improve this answer | |
  • 5
    You actually can read and write a file at the same time safely as long as the bytes are only being transformed, using the <> operator. – Chris Down Jun 6 '15 at 9:14
  • @ChrisDown: Yes, I mean without making it corroupt – cuonglm Jun 6 '15 at 9:19
  • I'm not sure what you mean about "making it corrupt". Unlike > and <, <> doesn't corrupt the file unless something went really wrong. You can quite easily write byte by byte using it. For example, try using it with tr. – Chris Down Jun 6 '15 at 20:01
  • 1
    @ChrisDown: Let me remove that sentence to avoid confusing. I actually mean when using <>file, you open file for reading and writing but you actually don't write anything to file. – cuonglm Jun 7 '15 at 7:12
  • 2
    I think the point that @ChrisDown is trying to make is that <> doesn't truncate a file, but merely replaces its existing bytes with the new output. If the new output is too short, you'll have leftover garbage at the end of the file. But if the new output is long enough, there's no risk. – BallpointBen Aug 2 '18 at 13:56
10

The moreutils home page itself documents a typical use case:

sed "s/root/toor/" /etc/passwd | grep -v joey | sponge /etc/passwd

Here, /etc/passwd is both being written to and read to, and is being modified. Without sponging up stdin before writing, /etc/passwd might be corrupted (as the file changed during reading).

| improve this answer | |
  • And that would be a good example on the moreutils page, if it had explained the way you did :-) – Br.Bill Jan 24 at 22:55

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.