How to convert HEIC image files to JPG in bash on macOS

We'll create a script that uses imagemagick to bulk convert HEIC files

· 2 min read
A magician waves a wand over a cauldron, which is a fitting metaphor to what we'll learn how to do to HEIC files
On the surface, using imagemagick might not seem as exciting as creating a potion, but it is actually pretty thrilling.

Apple iPhones store images in HEIC format (high efficiency image compression). HEIC has more advanced compression that JPG, which is great, the problem is that most other devices or websites can't use an HEIC file. Want to upload an iPhone photo to a website? You'll probably need to convert it first if you're on a desktop. Sure, there are ways to make it so that iOS stores your photos as JPG but then your photos take up more disk space.

Awhile ago, I created a bash script to automate the conversion process for me. For the script to work, you'll need to have imagemagick installed. I recommend first installing homebrew, a macOS package manager, and then installing imagemagick through that.

The script

#!/bin/bash

# 1
set -eu -o pipefail

# 2
count=$(find . -depth 1 -name "*.HEIC" | wc -l | sed 's/[[:space:]]*//')
echo "converting $count files .HEIC files to .jpg"

# 3
magick mogrify -monitor -format jpg *.HEIC

# 4
echo "Remove .HEIC files? [y/n]"
read remove

# 5
if [[ "$remove" == "y" ]]; then
  find . -depth 1 -name "*.HEIC" -delete
fi

Here's how it works:

  1. First, we set some bash settings to give us saner behavior in regards to errors. This is a great article on safe shell scripting that delves into that more deeply.

  2. We get a count of HEIC files in the directory it's being run in and write that to count stdout. I like to do this to just verify that the script is running in the right place. We use find with a depth of 1 so that we don't get do down subdirectories. This is then piped to wc -l which will return a count of the number of lines, effectively getting a count of files that'll be converted. From there we pipe to sed, because for reasons unknown to me, wc -l returns a number with several spaces in front of it, and the sed script just removes the whitespace.

  3. We run the imagemagick command that converts HEIC to JPG.

  4. We prompt the user if they also want to remove the HEIC files now that they've been converted. Whatever the user types and then hits enter will be stored to a variable named remove.

  5. If the user typed y, then we used find to delete all the HEIC files.

Make it available everywhere

There's multiple ways to expose a bash script to your PATH so it can be run anywhere. The way I do it is in my home directory, I have a folder called scripts. I added that folder to my PATH like so in my .zprofile:

export PATH="$PATH:$HOME/scripts"

I put the script above in that folder, gave it execute permissions (chmod +x) and voilà -- I can run that script anywhere in my bash shell terminal.

Depending on your needs, you could add more options to that script to choose what file format to convert to (we did jpg but you could also do png, for example). You could also make it enter subdirectories. Lots of fun possibilities.