Library

Optimize Images

Turn a folder of photos into WebP width variants with ImageMagick. Smaller sources are not upscaled, and existing files are skipped.

BASH Free to use
Code
#!/usr/bin/env bash
set -euo pipefail

find_magick() {
    if command -v magick >/dev/null 2>&1; then
        echo magick
        return
    fi

    if command -v convert >/dev/null 2>&1 \
        && convert -version 2>/dev/null | grep -qi imagemagick; then
        echo convert
        return
    fi

    echo "ImageMagick not found. Install magick and add it to PATH." >&2
    exit 1
}

optimize_one() {
    local src="$1"
    local dest_stem="$2"
    local magick="$3"
    local index width quality dest

    mkdir -p "$(dirname "$dest_stem")"

    for index in "${!WIDTHS[@]}"; do
        width="${WIDTHS[$index]}"
        quality="${QUALITIES[$index]:-${QUALITIES[-1]}}"
        dest="${dest_stem}-${width}.${FORMAT}"

        if [[ -f "$dest" && "$FORCE" -eq 0 ]]; then
            echo "EXISTS $dest"
            continue
        fi

        echo "CREATE $dest"
        "$magick" "$src" \
            -auto-orient \
            -strip \
            -resize "${width}x>" \
            -quality "$quality" \
            "$dest"
    done
}

INPUT="${1:?Usage: optimize-images <input> <output>}"
OUTPUT="${2:?Usage: optimize-images <input> <output>}"
INPUT="${INPUT%/}"
OUTPUT="${OUTPUT%/}"
FORMAT="${FORMAT:-webp}"
FORCE="${FORCE:-0}"
WIDTHS=(${WIDTHS:-480 960 1600})
QUALITIES=(${QUALITIES:-55 72 80})

magick="$(find_magick)"
mkdir -p "$OUTPUT"

if [[ -f "$INPUT" ]]; then
    optimize_one "$INPUT" "$OUTPUT/$(basename "${INPUT%.*}")" "$magick"
    exit 0
fi

if [[ ! -d "$INPUT" ]]; then
    echo "input not found: $INPUT" >&2
    exit 1
fi

while IFS= read -r -d '' src; do
    rel="${src#"$INPUT"/}"
    optimize_one "$src" "$OUTPUT/${rel%.*}" "$magick"
done < <(
    find "$INPUT" \
        \( -name .git -o -name node_modules -o -name optimized \) -prune -o \
        -type f \( -iname '*.jpg' -o -iname '*.jpeg' -o -iname '*.png' -o -iname '*.webp' \) \
        -print0
)
Quick try
chmod +x optimize-images
./optimize-images ./assets ./assets/optimized

WIDTHS="320 640 1280" QUALITIES="50 65 78" FORMAT=webp \
  ./optimize-images ./photos ./out

# assets/hero/station.jpg →
#   assets/optimized/hero/station-480.webp
#   assets/optimized/hero/station-960.webp
#   assets/optimized/hero/station-1600.webp

What it does

  • Needs ImageMagick 7+ as magick on PATH. Windows convert.exe is ignored on purpose.
  • ${width}x> resizes down only. A 700px photo will not be stretched to 1600px.
  • Existing outputs are skipped unless FORCE=1. This is a local batch tool, not an upload compressor.

Where it fits

A practical place for this snippet in a real project.

Useful before publishing a static site, so the HTML srcset can point at 480, 960, and 1600 WebP files. It is not a CDN image service.

Need a snippet that is not here?

Describe the problem or idea, and I will see if it belongs in the library.