#!/usr/bin/env bash # Optimizes everything the script can find in a folder, # meaning it will compress files as much as possible, # without losing any data (verification will be done # in order to verify that no data has been done) # (executable) # TODO Run in parallel # TODO Lots of dupplicated code there dir=${1:-$PWD} total=$(mktemp) echo -n 0 > $total function showtotal { echo "Total saved: $(cat "$total") bytes" rm $total exit } trap showtotal SIGTERM SIGINT SIGFPE function doReplace { # candidate original mv "$c" "$o" saved=$(($os - $cs)) perc=$((100 * $saved / $os)) echo "→ $os ⇒ $cs (saved $saved bytes, or ${perc}%)" newtotal=$(($(cat $total) + $saved)) echo -n $newtotal > $total } function replace { # candidate original c="$1" o="$2" # File verifications if [ ! -f "$o" ]; then echo "→ Original is inexistant, skipping!" return fi if [ ! -f "$c" ]; then echo "→ Candidate is inexistant, skipping!" return fi # Size verifications cs=$(wc -c "$c" | cut -d' ' -f1) os=$(wc -c "$o" | cut -d' ' -f1) if [ $cs -le 0 ]; then echo "→ Candidate is empty, skipping!" rm "$c" return fi if [ $cs -eq $os ]; then echo "→ Candidate weight the same, skipping." rm "$c" return fi if [ $cs -gt $os ]; then echo "→ Candidate is larger, skipping." rm "$c" return fi doReplace "$c" "$o" } function replaceImg { # candidate original # With bitmap verification c="$1" o="$2" # File verifications if [ ! -f "$o" ]; then echo "→ Original is inexistant, skipping!" return fi if [ ! -f "$c" ]; then echo "→ Candidate is inexistant, skipping!" return fi # Size verifications cs=$(wc -c "$c" | cut -d' ' -f1) os=$(wc -c "$o" | cut -d' ' -f1) if [ $cs -le 0 ]; then echo "→ Candidate is empty, skipping!" rm "$c" return fi if [ $cs -eq $os ]; then echo "→ Candidate weight the same, skipping." rm "$c" return fi if [ $cs -gt $os ]; then echo "→ Candidate is larger, skipping." rm "$c" return fi # Bitmap verification ppmc="$(mktemp --suffix .ppm)" ppmo="$(mktemp --suffix .ppm)" convert "$c" "$ppmc" convert "$o" "$ppmo" if cmp --silent "$ppmo" "$ppmc"; then doReplace "$c" "$o" else echo "→ Candidate don't have the same bit map as original, skipping!" fi rm -f "$ppmc" "$ppmo" "$c" } # JPEG (requires jpegtran) while read image do if [ -z "$image" ]; then continue; fi echo Processing $image prog=$(mktemp --suffix .jpg) jpegtran -copy all -progressive "$image" > "$prog" echo "→ Progressive done" progs=$(wc -c "$prog" | cut -d' ' -f1) replace "$prog" "$image" done <<< "$(find "$dir/" -type f -iregex ".+.jpe?g$")" # PNG (requires optipng) while read image do if [ -z "$image" ]; then continue; fi echo Processing $image temp=$(mktemp --suffix .png) cp "$image" "$temp" optipng -quiet "$temp" echo "→ Optimize done" replace "$temp" "$image" done <<< "$(find "$dir/" -type f -iname "*.png")" # FLAC (requires reflac) while read music do if [ -z "$music" ]; then continue; fi echo Processing $music temp_dir=$(mktemp --directory) temp="$temp_dir/to_optimize.flac" cp "$music" "$temp" reflac --best "$temp_dir" echo "→ Optimize done" replace "$temp" "$music" rm -rf "$temp_dir" done <<< "$(find "$dir/" -type f -iname "*.flac")" # # SVG (requires scour) # while read image # do # if [ -z "$image" ]; then continue; fi # echo Processing $image # # temp=$(mktemp --suffix .svg) # scour --quiet "$image" "$temp" --no-line-breaks # echo "→ Optimize done" # # replaceImg "$temp" "$image" # # done <<< "$(find "$dir/" -type f -iname "*.svg")" # NOTE Explicitely disabled since: # - I only have ~50 MiB of SVG in TOTAL # - Most conversions are not image losseless # - Even when they are losseless, they are mostly worthless # - I might want to keep editor data and/or ids for some of them # So rather use scour explicitely when needed cleandev showtotal