Hazel Rule or Applescript to Delete Image If it's already in Photos Library

I have a Hazel rules that imports (copies ) image files from my downloads folder into my Photos library.

Occasionally, I’ll download an image that I already have in my Photos library, and the Hazel rule gets stuck because Photos will open a window prompting me for how to handle the image file(skip or import).

From my research it looks like Hazel doesn’t have a built-in way to check if an image already exist in my Photos library, My idea is to write a script to do that check and delete the file if it’s already in the library.

I haven’t found a script online that does that, not even close enough to where I can modify it to do what I want to accomplish. I haven’t looked at Automator yet, so it might have that feature.

Are there any AppleScript gurus here who might be able to help out?

Update - I discovered you can use Javascript as well (JXA ) on Apple discussions. Discussion link

I don’t normally use javascript, but I’ll give it a go.

I don’t think there’s an easy way to script this, but if there is, I’d love to hear it.

My only real idea off the top of my head, is to have Keyboard Maestro monitor Photos.app after the import to look for the dialog box asking what you want to do with the duplicate.

You can have the Keyboard Maestro macro give up after X seconds if it doesn’t see the prompt (i.e. when it isn’t a duplicate).

That’s a pretty blunt-instrument “solution” though.

OTOH, searching your entire Photos database might not be much better, especially depending on how much info you have in there.

If wasn’t simple , but I found a Python library called osxphotos for working with the Photos Library. Python is my language of choice, so this was a good find.

It does take several seconds to run, so if I dumped a large number of images into my downloads folder, it could take a while to process them. But, I had my photo import rule turned off for months because of this issue. So I think it’s a good tradeoff.

In Hazel, I used the “Passes shell script” condition to run my script that returns 0 if the file is in the library, 1 if it is not.

Hazel Rules

Rule #1 If image file is older than 1 day and in photo library, move to Trash folder.
Rule #2 If image file is older than 1 day, import into Photos and move to backup images library folder on NAS.

Shell Script

#!/bin/bash

DIR=“$( cd “$( dirname “${BASH_SOURCE[0]}” )” >/dev/null 2>&1 && pwd )”

PROJECTDIR=$(dirname $DIR)

LOGFILE=“${PROJECTDIR}/output.log”

FILENAME=$(basename ${1})

echo “Running script $0 with arguments ${@}” # >> “${LOGFILE}” 2>&1

source $PROJECTDIR/venv/bin/activate

python $PROJECTDIR/photos_utils/image_exists.py --image_name ${FILENAME} # >> “${LOGFILE}” 2>&1

RC=$?

echo “Return code is ${RC}” # >> “${LOGFILE}” # 2>&1

echo " " #>> “${LOGFILE}” 2>&1

echo " " #>> “${LOGFILE}” 2>&1

deactivate

exit $RC

Python Script

import re 
import sys
import time 
import osxphotos
import argparse
from datetime import datetime


def create_arguments():
    parser = argparse.ArgumentParser(description='Returns 0 if image file exists in Photos Library. Else returns 1.')
    parser.add_argument('--image_name', action='store', dest='image_name',required=True, help='Name of image file')
    return parser.parse_args()

def main():
    args = create_arguments()
    photosdb = osxphotos.PhotosDB()    
    results =  [ photo for photo in photosdb.photos( movies=False, images=True ) if photo.original_filename == args.image_name ]
    if results:
        print("File exists in library")
        return 0
    else:
        print("File does not exist in library")
        return 1
    # print(results)
    return    


if __name__ == "__main__":
    start_time = datetime.now()
    results = main()  
    print(f"Script completed in {(datetime.now() - start_time).seconds} seconds.")
    sys.exit(results)

Note that Python is running in a virtual environment(venv act/deact lines ) atm. I’ll eventually change that.