Convert directory of images on the command line
I had a need, well I always have a need but I finally got around to figuring this out, to resize a directory of images. I finally broke up with Adobe and had historically used the Photoshop batch functionality which was always wonky at best so that’s no longer possible. I’ve done some digging and discovered yet again that Linux just does everything better. So without further adieu the command:
$ mogrify -path ./webp_images/ -format webp -quality 80 -resize 1200x1200\> *.jpg
Everything here is straightforward aside from the ‘\>’ after the resize flag. This extra bit prevents smaller images from being upscaled. FYI, you’ll need imagemagick installed to run the mogrify command.
Extra credit, here’s a command to mogrify a directory of images no matter the file type:
for img in *.{jpg,jpeg,png,bmp}; do [ -e "$img" ] && mogrify -path ./webp_images/ -format webp -quality 80 -resize 1200x1200\> "$img" done
UPDATE:
Here’s another example that will loop over a directory recursively and resize without upscaling and save as WEBP.
find . -maxdepth 1 -type f \( -iname '*.jpg' -o -iname '*.png' -o -iname '*.jpeg' -o -iname '*.bmp' \) -exec mogrify -path ./webp_images/ -format webp -quality 80 -resize 1200x1200\> {} +
UPDATE 2:
Here’s another example, a shell script, that will loop over a directory, save as WEBP and change the file name to include the directory that the image was found in.
#!/bin/bash # --- Configuration --- # Set the base directory to search for images. "." means the current directory. SOURCE_DIR="." # Set the directory where processed images will be saved. # The ~ will be expanded to your home directory. OUTPUT_DIR=~/web_images # --------------------- # Create the output directory if it doesn't already exist. # The '-p' flag prevents errors if the directory is already there. echo "Ensuring output directory exists at $OUTPUT_DIR..." mkdir -p "$OUTPUT_DIR" # Use 'find' to locate all image files recursively and process them. echo "Starting image processing..." find "$SOURCE_DIR" -type f \( -iname "*.jpg" -o -iname "*.jpeg" -o -iname "*.png" -o -iname "*.bmp" \) -exec bash -c ' # This inline script is executed for each file found by `find`. # The full path of the found file (e.g., ./subdir/image.jpg) is passed as the first argument ($1). # The destination directory is passed as the second argument ($2). file="$1" output_dir="$2" # 1. Get the parent directory name (e.g., "subdir"). parent_dir=$(basename "$(dirname "$file")") # 2. Get the filename without its original extension (e.g., "image"). base_name_no_ext=$(basename "${file%.*}") # 3. Construct the new filename by prepending the parent directory name. # If the image is in the source directory itself (parent is "."), we dont prepend ".-". if [ "$parent_dir" = "." ] || [ "$parent_dir" = "$SOURCE_DIR" ]; then new_name="${base_name_no_ext}.webp" else new_name="${parent_dir}-${base_name_no_ext}.webp" fi # 4. Define the full output path for the new image. output_path="${output_dir}/${new_name}" echo "Processing: \"$file\" -> \"$output_path\"" # 5. Use "convert" to resize, set quality, and save to the new path and format. # "1200x1200>" resizes only if the image is larger than 1200px on either side. convert "$file" -resize "1200x1200>" -quality 80 "$output_path" ' bash {} "$OUTPUT_DIR" \; # This passes the filename and output directory to the inline script echo "✅ Done."Published on August 5, 2025