Skip to content

Instantly share code, notes, and snippets.

@dmuth
Last active May 9, 2023 14:44
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save dmuth/0e9738ec6f6811649ea83c5be09f407d to your computer and use it in GitHub Desktop.
Save dmuth/0e9738ec6f6811649ea83c5be09f407d to your computer and use it in GitHub Desktop.
Shell script to recursively convert JPG and PNG files to HEIC format.
#!/bin/bash
#
# This script will convert JPG and PNG files to HEIC format recursively.
#
# Errors are fatal
set -e
GO=""
DELETE=""
JPG=""
function print_syntax() {
echo "! "
echo "! Syntax: $0 ( --go | -jpg ) [ --delete ] "
echo "! "
echo "! Recursively convert jpeg files to HEIC format or back to jpeg format."
echo "! "
echo "! --go - Do the conversion, otherwise this script will run in dry mode."
echo "! --jpg - Do the reverse and convert HEIC to JPEG. This should be used for uploading to Flickr/Facebook/etc."
echo "! --delete - Delete files that have been converted"
echo "! "
echo "! "
exit 1
} # End of print_syntax()
if test "$1" == "-h" -o "$1" == "--help"
then
print_syntax
fi
while test "$1"
do
if test "$1" == "--go"
then
GO=1
elif test "$1" == "--delete"
then
DELETE=1
elif test "$1" == "--jpg" -o "$1" == "--jpeg"
then
JPG=1
else
print_syntax
fi
shift
done
IFS=$'\n'
function convert_to_heic() {
#
# Deternine how many files need to be converted
#
NUM=0
NUM_CHECKED=0
I=1
echo "# Calculating number of files to convert (This may take a minute...)"
for FILE in $(find . -type f \( -iname \*.jpg -o -iname \*.jpeg -o -iname \*.png \))
do
TARGET=$(echo ${FILE} | sed -r 's/.[^.]+$/.heic/')
NUM_CHECKED=$(( NUM_CHECKED + 1 ))
if test $(( NUM_CHECKED % 100)) == 0
then
echo -n "${NUM_CHECKED} files checked.. "
fi
if test ! -s "${TARGET}"
then
NUM=$(( NUM + 1 ))
if test $(( NUM % 100)) == 0
then
echo -n "${NUM} files need converting.. "
fi
fi
done
echo
if test "${NUM}" == 0
then
if test "${DELETE}"
then
echo "# No files left to convert, but we're deleting files, so keep going..."
else
echo "# No files left to convert and we're not deleting anything, bailing out!"
return
fi
fi
for FILE in $(find . -type f \( -iname \*.jpg -o -iname \*.jpeg -o -iname \*.png \))
do
TARGET=$(echo ${FILE} | sed -r 's/.[^.]+$/.heic/')
if test "${GO}"
then
if test -s "${TARGET}"
then
echo "# Ooops--target file '${TARGET}' already exists, skipping!"
else
echo "# Converting file [${I}/${NUM}] '${FILE}' to '${TARGET}'..."
convert "${FILE}" -format heic "${TARGET}"
I=$(( I + 1 ))
fi
if test "${DELETE}"
then
echo "# Deleting source file ${FILE}..."
if test -s "${FILE}"
then
rm -fv "${FILE}"
else
echo "! Source file '${FILE}' is not a regular file, skipping deletion!"
fi
fi
else
if test -s "${TARGET}"
then
echo "# Ooops--target file '${TARGET}' already exists, skipping!"
else
echo "# Dry-Run -- not converting file [${I}/${NUM}] '${FILE}' to '${TARGET}'..."
I=$(( I + 1 ))
fi
fi
done
} # End of convert_to_heic()
#
# Convert HEIC back to JPEG.
# This is a slimmed down version of convert_to_heic()--it doesn't support deleting files,
# for example, as we normally want all roads to lead to HEIC.
#
function convert_to_jpg() {
#
# Deternine how many files need to be converted
#
NUM=0
NUM_CHECKED=0
I=1
echo "# Calculating number of files to convert..."
for FILE in $(find . -type f \( -iname \*.heic \) )
do
TARGET=$(echo ${FILE} | sed -r 's/.[^.]+$/.jpg/')
NUM_CHECKED=$(( NUM_CHECKED + 1 ))
if test $(( NUM_CHECKED % 100)) == 0
then
echo -n "${NUM_CHECKED} files checked.. "
fi
if test ! -s "${TARGET}"
then
NUM=$(( NUM + 1 ))
if test $(( NUM % 100)) == 0
then
echo -n "${NUM} files need converting.. "
fi
fi
done
echo
if test "${NUM}" == 0
then
if test "${DELETE}"
then
echo "# No files left to convert, but we're deleting files, so keep going..."
else
echo "# No files left to convert and we're not deleting anything, bailing out!"
return
fi
fi
for FILE in $(find . -type f \( -iname \*.heic \) )
do
TARGET=$(echo ${FILE} | sed -r 's/.[^.]+$/.jpg/')
if test -s "${TARGET}"
then
echo "# Ooops--target file '${TARGET}' already exists, skipping!"
else
echo "# Converting file [${I}/${NUM}] '${FILE}' to '${TARGET}'..."
convert "${FILE}" -format jpg "${TARGET}"
I=$(( I + 1 ))
fi
if test "${DELETE}"
then
echo "# Deleting source file ${FILE}..."
if test -s "${FILE}"
then
rm -fv "${FILE}"
else
echo "! Source file '${FILE}' is not a regular file, skipping deletion!"
fi
fi
done
} # End of convert_to_jpg()
if test ! "${JPG}"
then
convert_to_heic
else
convert_to_jpg
fi
echo "# Done!"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment