How to Bulk Process Images with ImageMagick in Bash?

Integrating the ImageMagick convert (or magick) command into a Bash script allows you to automate repetitive image editing tasks, such as resizing, format conversion, and watermarking, across thousands of files simultaneously. This article covers the essential syntax for constructing bulk-processing loops, handling file naming conventions safely, and optimizing performance using parallel processing. By the end of this guide, you will have a template script ready to deploy for any batch image-handling workflow.

The Basic For Loop Approach

The most straightforward way to process multiple images is by using a standard Bash for loop. This method iterates through every file matching a specific extension and applies the ImageMagick command individually.

#!/bin/bash

# Create an output directory to save processed images
mkdir -p processed_images

# Loop through all JPEG images in the current directory
for file in *.jpg; do
    # Check if files exist to avoid errors in empty directories
    [ -e "$file" ] || continue
    
    # Extract the filename without the extension
    filename=$(basename "$file" .jpg)
    
    # Resize the image and save it to the output folder
    convert "$file" -resize 800x600 "processed_images/${filename}_resized.jpg"
done

echo "Bulk processing complete!"

Handling Spaces and Format Conversion

When working with production assets, filenames often contain spaces or special characters, which can break poorly constructed scripts. Quotes around variables are vital. Additionally, you can easily change the file format during the process by changing the target extension.

#!/bin/bash

# Target all PNG files, even those with spaces in the name
for file in ./*.png; do
    [ -e "$file" ] || continue
    filename=$(basename "$file" .png)
    
    # Converts PNG to WebP while adjusting quality
    convert "$file" -quality 85 "processed_images/${filename}.webp"
done

Advanced: Speeding Up with Parallel Processing

If you need to process thousands of high-resolution images, processing them one by one can be slow. You can utilize xargs or GNU Parallel to maximize your CPU usage by running multiple ImageMagick instances at the same time.

Using xargs with multi-threading:

#!/bin/bash

# Finds all .jpg images and processes up to 4 of them concurrently
find . -maxdepth 1 -name "*.jpg" -print0 | xargs -0 -P 4 -I {} sh -c '
    backbone=$(basename "{}" .jpg)
    convert "{}" -strip -thumbnail 300x300 "processed_images/${backbone}_thumb.jpg"
'

Best Practices for Scripting with ImageMagick