How to Create a Bash Image Resizer

How to Create a Bash Image Resizer

How to Create a Bash Image Resizer

I once had a folder of a few hundred product photos, all at wildly inconsistent resolutions, that needed to be resized to a uniform dimension before uploading to an online store. Opening each one in an image editor would have taken hours. Instead, I wrote a small Bash script around ImageMagick, and what used to be an afternoon of tedious clicking became a five-second command. Here’s the full breakdown of how I built it.

Why Use Bash for Image Resizing

Bash itself doesn’t manipulate image data — that job belongs to dedicated image-processing libraries. But Bash is the perfect orchestration layer for:

The Tool Behind It: ImageMagick

The most common and powerful tool for this job is ImageMagick, specifically its convert (or newer magick) command.

Install it on Debian/Ubuntu:

sudo apt update
sudo apt install imagemagick

On Fedora:

sudo dnf install ImageMagick

On macOS (via Homebrew):

brew install imagemagick

The Simplest Resize Command

convert input.jpg -resize 800x600 output.jpg

This resizes input.jpg so it fits within an 800×600 bounding box while preserving the original aspect ratio (ImageMagick won’t distort the image unless you explicitly force exact dimensions).

A Basic Batch Resizer Script

#!/bin/bash

set -euo pipefail

target_size="800x600"
output_dir="resized"

mkdir -p "$output_dir"

for img in *.jpg *.png; do
    [ -e "$img" ] || continue
    convert "$img" -resize "$target_size" "$output_dir/$img"
    echo "Resized: $img"
done

echo "All images resized into '$output_dir/'"

How This Works Internally

Forcing Exact Dimensions (Ignoring Aspect Ratio)

Sometimes you need an exact width and height regardless of distortion, such as for a fixed-size thumbnail grid:

convert input.jpg -resize 300x300! output.jpg

The ! after the dimensions tells ImageMagick to ignore the original aspect ratio and force the exact size specified.

Resizing by Percentage

convert input.jpg -resize 50% output.jpg

This scales the image down to 50% of its original dimensions — useful when you want proportional resizing without specifying exact pixel values.

A More Advanced Script with Aspect Ratio Preservation and Quality Control

#!/bin/bash

set -euo pipefail

usage() {
    echo "Usage: $0 <width>x<height> <quality 1-100> <input_dir> <output_dir>"
    exit 1
}

if [ "$#" -ne 4 ]; then
    usage
fi

dimensions="$1"
quality="$2"
input_dir="$3"
output_dir="$4"

mkdir -p "$output_dir"

find "$input_dir" -maxdepth 1 -type f \( -iname "*.jpg" -o -iname "*.jpeg" -o -iname "*.png" \) -print0 |
while IFS= read -r -d '' img; do
    filename=$(basename "$img")
    convert "$img" -resize "$dimensions" -quality "$quality" "$output_dir/$filename"
    echo "Processed: $filename"
done

echo "Batch resize complete."

Breaking Down the Key Parts

Generating Thumbnails Alongside Full-Size Images

A common real-world pattern is generating both a resized “display” version and a small thumbnail:

#!/bin/bash

set -euo pipefail

input_dir="$1"
display_dir="display"
thumb_dir="thumbnails"

mkdir -p "$display_dir" "$thumb_dir"

find "$input_dir" -maxdepth 1 -type f -iname "*.jpg" -print0 |
while IFS= read -r -d '' img; do
    filename=$(basename "$img")
    convert "$img" -resize 1200x1200 "$display_dir/$filename"
    convert "$img" -resize 150x150 "$thumb_dir/$filename"
done

echo "Generated display and thumbnail versions."

This produces two output sets from a single source directory — a larger display-ready version and a small thumbnail — in one pass.

Converting Format While Resizing

ImageMagick can also convert formats as part of the same command:

convert input.png -resize 800x600 output.jpg

This resizes a PNG and outputs it as a JPEG in a single step, which is handy when standardizing a mixed-format image library.

Real-World Use Cases

Automation Example

Here’s a script I run via a folder-watching cron job to automatically resize new uploads as they arrive:

#!/bin/bash

set -euo pipefail

watch_dir="/data/uploads"
processed_dir="/data/uploads_resized"
log_file="/var/log/image_resizer.log"

mkdir -p "$processed_dir"

find "$watch_dir" -maxdepth 1 -type f -iname "*.jpg" -newer /tmp/last_run_marker -print0 |
while IFS= read -r -d '' img; do
    filename=$(basename "$img")
    convert "$img" -resize 1024x1024 -quality 85 "$processed_dir/$filename"
    echo "$(date '+%F %T') Resized $filename" >> "$log_file"
done

touch /tmp/last_run_marker

The -newer /tmp/last_run_marker flag ensures only files added since the last run are processed, making this safe to run repeatedly via cron without reprocessing everything each time.

Best Practices

Security Considerations

Optimization Tips

convert input.jpg -resize 800x600 -strip -quality 85 output.jpg
find . -maxdepth 1 -iname "*.jpg" -print0 | xargs -0 -P 4 -I{} convert {} -resize 800x600 resized/{}

Troubleshooting Common Issues

Problem: convert: command not found. Install ImageMagick via your package manager, and confirm with convert -version.

Problem: Resized images look distorted. You likely used the ! flag unintentionally, forcing exact dimensions and ignoring the original aspect ratio.

Problem: Output images are much larger than expected. Add -strip to remove unnecessary metadata, and adjust -quality to a lower value for JPEGs.

Problem: Script fails on filenames with spaces or special characters. Switch from a plain glob loop to find -print0 combined with while IFS= read -r -d ''.

Problem: “convert-im6.q16: not authorized” errors. This is usually due to ImageMagick’s security policy blocking certain formats (like PDF). Check /etc/ImageMagick-6/policy.xml and adjust cautiously if you understand the security implications.

Common Mistakes to Avoid

Frequently Asked Questions

Does resizing reduce image quality? Downscaling generally preserves visual quality well; it’s aggressive JPEG compression (low -quality values) or upscaling that introduces noticeable quality loss.

Can I resize images without ImageMagick? Yes, alternatives include ffmpeg (also handles images) or vipsthumbnail from libvips, which is often faster for very large batches.

How do I resize only if the image is larger than the target size? Add a > after your dimensions: convert input.jpg -resize 800x600\> output.jpg, which only shrinks images larger than the target, leaving smaller ones untouched.

Can this resize animated GIFs? Yes, but you typically need the -coalesce flag before resizing to handle each frame correctly: convert input.gif -coalesce -resize 400x400 output.gif.

What’s the difference between convert and mogrify? convert creates a new output file, while mogrify modifies images in place (or writes to a directory specified with -path) — useful for quick batch edits without managing separate output filenames.

Summary

A Bash image resizer built around ImageMagick’s convert command scales from a single one-line command to a fully automated batch-processing pipeline capable of handling thumbnails, format conversion, and quality optimization. The details that matter most: preserve aspect ratio by default, strip unnecessary metadata to save space, use find -print0 for safe filename handling, and always keep your resized output separate from your originals.

References

Exit mobile version