Skip to content

Instantly share code, notes, and snippets.

@dzogrim
Last active August 8, 2019 18:46
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dzogrim/7552134d4b0f4409c2dafa1bed080ea4 to your computer and use it in GitHub Desktop.
Save dzogrim/7552134d4b0f4409c2dafa1bed080ea4 to your computer and use it in GitHub Desktop.
macOS Messages App attachments clean-up (this will remove attachments from Messages App history!)
#!/bin/bash
## macOS 'Messages.app' attachments clean-up
## Main known media formats files will be moved to trash to save space
## Copyleft (C) 2018-2019 dzogrim
## dzogrim < dzogrim [@] dzogrim [.] pw >
#VERSION="1.0 (2018-04-07)" # initial
#VERSION="1.1 (2018-05-28)" # sort garbage
#VERSION="1.1.1 (2018-07-23)" # more formats
#VERSION="1.1.2 (2018-08-01)" # more formats
#VERSION="1.1.3 (2019-04-20)" # more formats
#VERSION="1.2 (2019-06-23)" # rewriting and up to 20 formats
#VERSION="1.2.1 (2019-07-13)" # more formats
#VERSION="1.3 (2019-08-08)" # handle a better way duplicates filenames without overwrite
# Controls
[[ "$( uname )" != *"Darwin"* ]] && \
printf "\n${bldred}[ERROR]${txtrst} This tool was designed to run on macOS systems.\n" && \
exit 1
# Configuration
pathToClean=$HOME/Library/Messages/Attachments
pathToTrash=$HOME/.Trash/
fileFormats='m4r\|xml\|m4v\|pps\|docx\|odt\|zip\|sh\|txt\|pdf\|jpg\|gif\|png\|jpeg\|mov\|vcf\|amr\|caf\|mp3\|m4a\|mp4\|3gp\|HEIC\'
SECONDS=0
# Move files behaviour
mvopt1="--backup=numbered"
mvopt2="--no-clobber"
# Text color variables
txtbld=$(tput bold) # bold
bldred=${txtbld}$(tput setaf 1) # red
bldgrn=${txtbld}$(tput setaf 2) # green
bldbrw=${txtbld}$(tput setaf 3) # brown
txtrst=$(tput sgr0) # reset
checkTools()
{
local misstools
for entry in "$@"
do
if ! which "${entry}" >/dev/null 2>&1
then
misstools="${misstools} ${entry}"
fi
done
[ -z "${misstools}" ] \
&& return \
|| {
printf "\n ${NAME} require tools that could not be found: \n ${misstools}\n"
exit 1
}
}
checkTools gfind gmv
whereTo()
{
case "$1" in
"*.vcf") destfolder="cards";;
"*.gif") destfolder="gifs";;
"Screenshot*"|"Capture*.png") destfolder="screenshots";;
"*.png"|"*.jpg"|"*.jpeg"|"*.heic") destfolder="images";;
"*.mov"|"*.m4v"|"*.mp4"|"*.3gp") destfolder="videos";;
"*.docx"|"*.zip"|"*.sh"|"*.odt"|"*.pdf"|"*.txt"|"*.xml"|"*.pps") destfolder="docs";;
"*.amr"|"*.m4a"|"*.mp3"|"*.caf"|"*.m4r") destfolder="audio";;
esac
}
dispatchFiles()
{
local findopt="-mindepth 1 -maxdepth 1 -type f"
for entry in "$@"
do
counter_total="$( gfind "${pathToTrash}" ${findopt} -iname "${entry}" | wc -l )"
if [[ ${counter_total} -ge 1 ]]; then
# Initialize destination directory for this entry
whereTo "${entry}"
mkdir -p "${pathToTrash}/${destfolder}"
gfind "${pathToTrash}" ${findopt} -iname "${entry}" -exec gmv ${mvopt1} '{}' -t "${pathToTrash}/${destfolder}/" \;
fi
done
}
renameNumberedMoves()
{
if [[ "$( gfind ${pathToTrash} -mindepth 1 -maxdepth 1 -type f -iname '*.~*~*' | wc -l )" -gt 1 ]]; then
pushd "${pathToTrash}" >/dev/null 2>&1
for f_name in *.~*~; do
f_bak_ext="${f_name##*.}"
f_bak_num="${f_bak_ext//[^0-9]/}"
f_orig_name="${f_name%.*}"
f_only_name="${f_orig_name%.*}"
f_only_ext="${f_orig_name##*.}"
gmv ${mvopt2} "$f_name" "$f_only_name ($f_bak_num).$f_only_ext"
done
popd >/dev/null 2>&1
fi
}
# Calculate iMessage attachments size
[ ! -d "${pathToClean}" ] && printf "\n${bldred}[ERROR]${txtrst} Missing attachments directory.\n" && exit 1
printf "\n${bldgrn}[START]${txtrst} Used space size is %s of attachments files.\n" \
"$(du -sh "${pathToClean}" | awk '{print $1}')"
# Move iMessage attachments to trash can
[ ! -d "${pathToTrash}" ] && printf "\n${bldred}[ERROR]${txtrst} Missing destination directory.\n" && exit 1
gfind "${pathToClean}" -type f -iregex ".*\.\(${fileFormats})" -exec gmv ${mvopt1} "{}" -t "${pathToTrash}" \;
# Remove iMessage Payload Attachments
gfind "${pathToClean}" -type f -iname "*.pluginPayloadAttachment" -delete
# Remove empty directories
gfind "${pathToClean}" -type f -name '.DS_Store' -delete
gfind "${pathToClean}" -mindepth 1 -type d -empty -delete
# Recalculate iMessage attachments size after clean-up
printf "\n${bldgrn}[STOP]${txtrst} Reduced used space size to only %s.\n" \
"$(du -sh "${pathToClean}" | awk '{print $1}')"
# Handle duplicates filenames without overwrite before dispatching
renameNumberedMoves
# Sort trashed files as defined in 'fileFormats' and expected by 'whereTo'
dispatchFiles "Screenshot*" "Capture*.png" "*.vcf" "*.docx" "*.pdf" "*.txt" "*.xml" "*.pps" \
"*.gif" "*.amr" "*.m4a" "*.mp3" "*.caf" "*.m4r" "*.png" "*.jpg" "*.jpeg" "*.heic" \
"*.mov" "*.m4v" "*.mp4" "*.3gp" "*.odt" "*.zip" "*.sh"
# Show how many time it took
duration=$SECONDS
printf "\n${bldbrw}[INFO]${txtrst} %s seconds elapsed.\n\n" "$(( duration % 60 ))"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment