2

I'm trying to optimize sample.jpg with mozcjpeg, but I want it to compress sample.jpg, and not creating another file.

I run this command:

mozcjpeg -quality 80 sample.jpg > sample.jpg

and I get

Empty input file

What's the right way to do it?

P.S. I have a bash script that runs once a day to optimize images created in the last 24 hours.

Grin
  • 557
  • 1
  • 6
  • 19

3 Answers3

0

Just use a different output file name, otherwise it gets immediately overwritten.

Vadim Landa
  • 2,784
  • 5
  • 23
  • 33
  • Vadim, I need to overwrite original file, that's what the question is about. jpegtran can do that, so I think mozjpeg can do it too. – Grin Apr 25 '17 at 13:12
0

You’re reading the file and overwriting it at the same time. Instead, make an intermediary file:

tmp_file="$(mktemp)"
mozcjpeg -quality 80 sample.jpg > "${tmp_file}"
mv "${tmp_file}" sample.jpg
user137369
  • 5,219
  • 5
  • 31
  • 54
0

anycmd foo.jpg > foo.jpg is understood as:

  • The shell will open foo.jpg for write (overwriting any existing data).
  • The shell will fork and set this open file as the stdout.
  • The shell will exec anycmd foo.jpg.

So, by the time the command is executed, the original file is already gone. How can you work around that?

Well, you can create a temporary file, as suggested in the other answer.

Alternatively, you can use sponge. It's part of moreutils package.

$ whatis sponge
sponge (1)           - soak up standard input and write to a file

This tool allows you to write:

mozcjpeg -quality 80 sample.jpg | sponge sample.jpg

It works because sponge will first read all of the stdin (in memory), and only after stdin reaches EOF it will open the file for writing.

Denilson Sá Maia
  • 47,466
  • 33
  • 109
  • 111