21

While doing some work, I found this "sponge" command that does the same as "tee", but could not find when it is better to use one or the other.

Can someone explain?

Rakib Fiha
  • 473
  • 8
  • 13
crsuarezf
  • 1,201
  • 3
  • 18
  • 33
  • 1
    On any Linux I have within reach, there is no `soak` command. Only `tee`. I have never heard of the former at all until now. Did you mean [`sponge`](http://linux.die.net/man/1/sponge) perhaps? – Two-Bit Alchemist Nov 10 '15 at 20:08
  • Are you refering to 'sponge' command? "sponge - soak up standard input and write to a file" – alsjflalasjf.dev Nov 10 '15 at 20:13
  • I edited my question. @Two-BitAlchemist yep. is sponge – crsuarezf Nov 11 '15 at 17:25
  • 1
    OK. I would like to add to this, in case I didn't make it clear: `tee` is going to be on 99.99% of Linux installs you find. This `sponge` needs to be specially installed and may not even be available for certain distros (I have no idea). Anyway, don't count on it just being available. This is especially important if you're writing shell scripts you intend to distribute. – Two-Bit Alchemist Nov 12 '15 at 15:33
  • Well I was writing a spec for a rpm package and I had to put sponge in the requires section. – crsuarezf Nov 13 '15 at 18:18
  • Thank goodness this question appeared among all the Spongebob Squarepants t-shirt search results. – Sridhar Sarnobat Apr 26 '17 at 02:55
  • 3
    For anyone looking to install `sponge`: on Debian [`apt-get install moreutils`](https://packages.debian.org/unstable/utils/moreutils). – 0 _ Nov 25 '17 at 07:07
  • For debian: `sudo apt install moreutils -y` For macOS `brew install moreutils` – Rakib Fiha Nov 20 '19 at 18:05
  • For Cygwin ;) `apt-cyg install moreutils` – golimar Apr 30 '21 at 12:06

2 Answers2

41

No one of them soak up stderr; only stdout. 'tee' writes stdin on stdout and files. 'sponge' writes stdin only on a file; without errors, no output. (i.e: Unlike 'tee', 'sponge' doesn't write on stdout). Besides,

"sponge soaks up all its input before opening the output file"

(from its manual)

This difference between them is extremely relevant: 'tee' "reads a byte", and "writes that byte"; 'sponge' waits to receive all the input, and then, writes it.

Pridkett
  • 4,883
  • 4
  • 30
  • 47
alsjflalasjf.dev
  • 1,589
  • 13
  • 11
  • Any specific use cases why one might use `sponge` over `tee`? Generally streaming is good I would guess. I know sorting requires full input, but what would be an example command? – Sridhar Sarnobat Apr 26 '17 at 02:58
  • 5
    `expand foo.txt | sponge foo.txt`, see also: https://unix.stackexchange.com/q/207919/43390 – 0 _ Nov 25 '17 at 07:09
  • Just to add another use case: When using automated scripts that write to files and may block, those files will leave their file descriptors open for an indefinite amount of time. This is especially a problem when working with cron. See: https://wiki.archlinux.org/index.php/Cron#Long_cron_job – Prouflon Dec 14 '20 at 12:36
  • 1
    @SridharSarnobat if you have a different tool that reads the output file, the it might read a partial file and crash it fail. Using sponge ensures that you have the entire content and not partial. – Peter Mar 17 '23 at 12:35
5

in practice there is a huge difference if your doing iterative processing; as tee will read byte by byte, you may end up with blank file due instisfatory redirects if your source file is also the target file. Sponge, will read all the input before starting to write to an open file.

tee will not produce the desired output

tf=/tmp/simple
jq -n '.name="Doe"' > $tf
cat $tf
> { "name": "Doe" }
jq '.name' $tf | tee $tf
cat $tf
> 
> #no output, file is blank

sponge will produce the desired output

tf=/tmp/simple
jq -n '.name="Doe"' > $tf
cat $tf
> { "name": "Doe" }
jq '.name' $tf | sponge $tf
cat $tf
> "Doe"
> # we got the expected output
Thiago Conrado
  • 726
  • 8
  • 15