Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Recursively optimize all PNG and JPG files wherever they are from the script position and inner ( based on OPTING, PNGCRUSH, ADVANCECOMP and JPEGOPTIM )
#!/bin/bash
# Improved as per feedback from @pascal - https://gist.github.com/julianxhokaxhiu/c0a8e813eabf9d6d9873#gistcomment-3086462
find . -type f -iname "*.png" -exec optipng -nb -nc {} \;
find . -type f -iname "*.png" -exec advpng -z4 {} \;
find . -type f -iname "*.png" -exec pngcrush -rem gAMA -rem alla -rem cHRM -rem iCCP -rem sRGB -rem time -ow {} \;
find . -type f \( -iname "*.jpg" -o -iname "*.jpeg" \) -exec jpegoptim -f --strip-all {} \;
@julianxhokaxhiu

This comment has been minimized.

Copy link
Owner Author

@julianxhokaxhiu julianxhokaxhiu commented Nov 18, 2019

Thanks for letting me know, I'll update it just to make sure everybody is aware of those improvements!

@v1993

This comment has been minimized.

Copy link

@v1993 v1993 commented Mar 1, 2020

Why aren't you using -exec for find?

@julianxhokaxhiu

This comment has been minimized.

Copy link
Owner Author

@julianxhokaxhiu julianxhokaxhiu commented Mar 1, 2020

Done, thanks for the suggestion. The snippet was quite old and I never paid attention to details.

@v1993

This comment has been minimized.

Copy link

@v1993 v1993 commented Mar 1, 2020

Suggestions:

  • Get rid of -print0 as it is not useful without xargs
  • Use \+ instead of \; if program supports taking few files as arguments (like optipng)

Why use -nb -nc with optipng, by the way? I don't think removing those will harm in most cases.

@julianxhokaxhiu

This comment has been minimized.

Copy link
Owner Author

@julianxhokaxhiu julianxhokaxhiu commented Mar 1, 2020

Updated again, thanks for the suggestions.

  1. Done.
  2. Feel free to test if it works on all and just let me know where it can be applied.

About the flags tbh it's been a long time since I do not use them, this gist is just there left in memory for whomever wants to use it :)

@astier

This comment has been minimized.

Copy link

@astier astier commented Mar 26, 2020

You could use -iname and squash statements like:

find . -type f -name "*.jpg" -o -name "*.JPG" -exec jpegoptim -f --strip-all {} \;

to

find . -type f -iname "*.jpg" -exec jpegoptim -f --strip-all {} \;

Now you can merge both jpg statements to one like:

find . -type f -iname "*.jpg" -o -iname "*.jpeg" -exec jpegoptim -f --strip-all {} \;

This is how it could look like:

find . -type f -iname "*.png" -exec optipng -nb -nc {} \;
find . -type f -iname "*.png" -exec advpng -z4 {} \;
find . -type f -iname "*.png" -exec pngcrush -rem gAMA -rem alla -rem cHRM -rem iCCP -rem sRGB -rem time -ow {} \;
find . -type f -iname "*.jpg" -o -iname "*.jpeg" -exec jpegoptim -f --strip-all {} \;
@astier

This comment has been minimized.

Copy link

@astier astier commented Mar 26, 2020

Additionally your and mine code have a bug. -exec ignores everything before -o.
My exec-statement as well as yours above should look like:

find . -type f \( -iname "*.jpg" -o -iname "*.jpeg" \) -exec jpegoptim -f --strip-all {} \;
@julianxhokaxhiu

This comment has been minimized.

Copy link
Owner Author

@julianxhokaxhiu julianxhokaxhiu commented Mar 26, 2020

Thanks, updated as well.

@astier

This comment has been minimized.

Copy link

@astier astier commented Mar 26, 2020

-iname is to make it case-insensitive. This means you do not need -iname "*.png" -o -iname "*.PNG". -iname "*.png" is enough because it automatically searches for *.PNG as well. You could make it:

find . -type f -iname "*.png" -exec optipng -nb -nc {} \;
find . -type f -iname "*.png" -exec advpng -z4 {} \;
find . -type f -iname "*.png" -exec pngcrush -rem gAMA -rem alla -rem cHRM -rem iCCP -rem sRGB -rem time -ow {} \;
find . -type f \( -iname "*.jpg" -o -iname "*.jpeg" \) -exec jpegoptim -f --strip-all {} \;
@julianxhokaxhiu

This comment has been minimized.

Copy link
Owner Author

@julianxhokaxhiu julianxhokaxhiu commented Mar 26, 2020

Ah right, sorry forgot about it. I was lazy and just run a full search and replace.

@ivanvart

This comment has been minimized.

Copy link

@ivanvart ivanvart commented May 9, 2020

Thanks for the script... I added a flag just to optimize newer images than last run in order to make it faster each run.
find . -type f -newer optimg.flag -iname "*.png" -exec optipng -nb -nc {} \;
find . -type f -newer optimg.flag -iname "*.png" -exec advpng -z4 {} \;
find . -type f -newer optimg.flag -iname "*.png" -exec pngcrush -rem gAMA -rem alla -rem cHRM -rem iCCP -rem sRGB -rem time -ow {} \;
find . -type f -newer optimg.flag \( -iname "*.jpg" -o -iname "*.jpeg" \) -exec jpegoptim -f --strip-all {} \;
touch optimg.flag

@mkormendy

This comment has been minimized.

Copy link

@mkormendy mkormendy commented Sep 10, 2020

I wouldn't use optipng nor pngcrush, pngquant is far superior than either of those two combined.
https://pointlessramblings.com/posts/pngquant_vs_pngcrush_vs_optipng_vs_pngnq/

@mkormendy

This comment has been minimized.

Copy link

@mkormendy mkormendy commented Sep 10, 2020

Oh, and instead of using \( -iname "*.jpg" -o -iname "*.jpeg" \) .. you can simply just use -iregex .*\.jpe?g$ in place.

@pduchnovsky

This comment has been minimized.

Copy link

@pduchnovsky pduchnovsky commented Nov 9, 2020

Improved script that actually runs even if file optimg.flag is not created yet.
Also ignores specific directories if needed

https://gist.github.com/pduchnovsky/9544ea3447b48c65c2412f7d5aef1f7a

@mskochev

This comment has been minimized.

Copy link

@mskochev mskochev commented Feb 21, 2021

Thanks for the nice scripts. Is there a way to run them multithreaded?

@uPagge

This comment has been minimized.

Copy link

@uPagge uPagge commented Feb 26, 2021

@pduchnovsky why are you using the -f flag in jpegoptim. For me it increases the size of the images if they have already been optimized better. Everything works much better without it.

@pduchnovsky

This comment has been minimized.

Copy link

@pduchnovsky pduchnovsky commented Feb 27, 2021

@pduchnovsky why are you using the -f flag in jpegoptim. For me it increases the size of the images if they have already been optimized better. Everything works much better without it.

I mean, this was in original script so I re-used it, but I wonder it might have something to do with using progressive optimization as well as stripping all metadata, which possibly would not happen if it's not forced and the file is already smaller.
Basically ensures that all of your files are optimized the same way.

@julianxhokaxhiu

This comment has been minimized.

Copy link
Owner Author

@julianxhokaxhiu julianxhokaxhiu commented Feb 27, 2021

Basically ensures that all of your files are optimized the same way.

Yes that was the case, nevertheless as things move forward, if there's a better way to tweak this script, I'm open to update it. Let me know what needs to be updated, and I'll do accordingly :)

Thanks to everyone coming here and saying hi, I appreciate any feedback and I'm glad you find this useful. Most of the time I do create gists for myself as a reminder for the future, but I'm glad others find it useful too.

@greg-randall

This comment has been minimized.

Copy link

@greg-randall greg-randall commented Jun 15, 2021

Unless you're using the AdvanceMame emulator to generate PNGs you can skip the advpng line. https://linux.die.net/man/1/advpng

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment