Skip to content

Instantly share code, notes, and snippets.

@julianxhokaxhiu
Last active February 19, 2024 05:04
Show Gist options
  • Save julianxhokaxhiu/c0a8e813eabf9d6d9873 to your computer and use it in GitHub Desktop.
Save julianxhokaxhiu/c0a8e813eabf9d6d9873 to your computer and use it in GitHub Desktop.
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 {} \;
@v1993
Copy link

v1993 commented Mar 1, 2020

Why aren't you using -exec for find?

@julianxhokaxhiu
Copy link
Author

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

@v1993
Copy link

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
Copy link
Author

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
Copy link

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
Copy link

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
Copy link
Author

Thanks, updated as well.

@astier
Copy link

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
Copy link
Author

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

@ivanvart
Copy link

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
Copy link

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
Copy link

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

@pduchnovsky
Copy link

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
Copy link

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

@uPagge
Copy link

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
Copy link

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
Copy link
Author

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
Copy link

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