0

Ok so this is a complex script that I hope someone out-there can help me with because I have spent the entire day trying to figure this out.

Lets say I collect cat images from Instagram and I have many folders of different cats on my computer. I identify each of them by adding a comment in the macOS "get info" section of each folder with the Instagram account name of each cat. For example: @juniorcat

I use Hazel (noodlesoft.com) to sort my folders automatically but it does not know how to merge the contents of the new folder with the old folder. So I have to make an embedded Applescript.

This script I put together is a combination of many others I found on the Internet and it does the following:

  1. It searches the parent directory of the new folder to see if there is an old folder with the same "get info" comment of @juniorcat that exist. It does this by searching for all folders in that directory that have NOT been added today.

  2. If there is an old folder that does have @juniorcat in the "get info" comments section, then the script will move all the images from the new folder, to the old folder.

  3. The script will then sequentially rename all of the images that have been moved to the old folder with the name of that folder and with the lowest number available. For example: Junior the Cat 5.jpg, Junior the Cat 6.jpg, etc.

I got 1 and 2 working correctly, but I am having issues with getting the script to rename ONLY the files I move to the old folder and not the entire contents of that folder.

I get the following error whenever I try:

error "Can’t get name of \"/Users/david/Desktop/Beautiful Cats/Junior the Cat/test7.jpg\"." number -1728 from name of "/Users/david/Desktop/Beautiful Cats/Junior the Cat/test7.jpg"

Here is the script:

set theFile to ":Users:david:Desktop:Beautiful Cats:Junior the Cat-1" as alias
--This is the Hazel matched folder that is renamed with a  "-1" at the end because a duplicate name exist.

set inputAttributes to "@juniorcat"
--The comment I add to identify the Instagram Account of each folder.

--Embedded Hazel Script starts here

set parentFolder to POSIX file (do shell script "dirname " & quoted form of POSIX path of (theFile))
set parentPath to quoted form of POSIX path of parentFolder
set spotlight1 to "mdfind -onlyin " & parentPath & " 'kMDItemDateAdded <= $time.today && kMDItemContentType == public.folder && kMDItemFinderComment ==  " & inputAttributes & "'"
set oldFolder to (do shell script spotlight1)

-- The above shell script is a spotlight search of folders that contain the same comment and have NOT been added today. This is to get the old existing folder.

-- Move Files Script

if (oldFolder = "") then
else
    set targetFolder to (POSIX file oldFolder) as alias

    tell application "Finder"
        move (entire contents of theFile) to the targetFolder
    end tell

    -- Select the Images added

    set targetPosix to quoted form of POSIX path of targetFolder

    set command2 to "mdfind -onlyin " & targetPosix & " 'kMDItemDateAdded >= $time.today && kMDItemKind = *image'"
    set movedImages to paragraphs of (do shell script command2)

    --Rename all the images selected from the above shell script

    set text item delimiters to "."
    tell application "Finder"
        set all_files to every item of movedImages

        -- If you replace "movedImages" with "targetFolder", it will name all of the files in that folder. I only want to rename the files I move into this folder.

        set new_name to name of folder targetFolder
        repeat with index from 1 to the count of all_files
            set this_file to item index of all_files
            set {itemName, itemExtension} to {name, name extension} of this_file
            if index is less than 10 then
                set index_prefix to " "
            else
                set index_prefix to " "
            end if
            if itemExtension is "" then
                set file_extension to ""
            else
                set file_extension to "." & itemExtension
            end if
            set the name of this_file to new_name & index_prefix & index & file_extension as string
        end repeat
    end tell
end if
3
  • There seems to be some duplication of effort. theFile is a folder path of the source files? Why are you getting all the files but then performing another search to determine what to rename? Are you planning on using different separators?
    – red_menace
    Dec 16 '19 at 1:18
  • That is what exactly what I am trying to do CJK (I want to make all of the files that are moved into the old folder an "alias file" in the script). The problem is I do not know how. The script works when you replace the "movedImages" with "targetFolder" at the bottom. But then it will rename all of the images in that folder. I only want to rename the images that are moved into the folder.
    – David
    Dec 16 '19 at 12:21
  • red_menace, yes theFile is the source of the files. I am getting all of the images in that folder then moving them into the old existing folder (which already has images of Junior the Cat). I am performing another spotlight search to select only the files that have been added today to the old folder. (That way it does not select the old images). Then I will rename those images sequentially starting with the lowest number available in that folder.
    – David
    Dec 16 '19 at 12:28
0

A few things about your script:

  • It moves everything from the source folder and then searches again to find items to rename;
  • It just gets all the items and renames them with a suffix without looking at what is already there;
  • I'm not sure about using the reserved term index as a variable name.

I've added a handler to get a name for items in the destination folder. It adds a numerical suffix to the name part and checks against what is already there, continuing until the name is unique. I also consolidated the move and rename parts and gave more descriptive names to variables (to make it easier to work with), so if my test search terms weren't too far off, this should be close to what you are looking for:

script Hazel -- encapsulate a regular script (including handlers) to use as embedded

    property sourceFolder : missing value
    property attributes : missing value

    # Find an existing folder to add to
    tell application "Finder" to set parentFolder to quoted form of POSIX path of ((container of sourceFolder) as text)
    set spotlight1 to "mdfind -onlyin " & parentFolder & " 'kMDItemDateAdded <= $time.today && kMDItemContentType == public.folder && kMDItemFinderComment ==  " & inputAttributes & "'"
    set destinationFolder to (do shell script spotlight1)

    if destinationFolder is not "" then
        # Get a list of added items from sourceFolder
        set spotlight2 to "mdfind -onlyin " & quoted form of POSIX path of sourceFolder & " 'kMDItemDateAdded >= $time.today && kMDItemKind = *image'"
        set movedImages to paragraphs of (do shell script spotlight2)

        # Move and rename the items selected from the above shell script
        tell application "Finder"
            set destinationFolder to destinationFolder as POSIX file as alias -- coerce from POSIX
            set baseName to name of destinationFolder
            repeat with anItem in movedImages
                set anItem to anItem as POSIX file as alias -- coerce from POSIX
                set theExtension to name extension of anItem
                if theExtension is not "" then set theExtension to "." & theExtension
                set movedFile to (move anItem to destinationFolder) -- get a reference to the moved file
                set newName to my (getUniqueName for baseName & theExtension from destinationFolder)
                set name of movedFile to newName
            end repeat
        end tell
    end if

    # Check someName against items in someFolder, adding a suffix as needed to get a unique name
    to getUniqueName for someName from someFolder
        set {separator, counter} to {" ", 0} -- starting suffix, or 0 to always add a suffix starting at 1
        set leadingZeros to 0 -- maximum leading zeros (1-6), or 0 for none

        set here to -(offset of "." in ((reverse of text items of someName) as text)) - 1 -- split extension at last period
        set theName to text 1 thru here of someName
        if here is -1 then -- no extension
            set theExtension to ""
        else
            set theExtension to text (here + 1) thru -1 of someName
        end if

        if counter < 1 then
            set counter to 1
            if leadingZeros > 0 then set counter to text -(leadingZeros + 1) thru -1 of ("000000" & counter)
            set newName to theName & separator & counter & theExtension
        else
            set newName to theName & theExtension
        end if
        tell application "System Events" to tell (get name of items of folder (someFolder as text) whose visible is true)
            repeat while it contains newName
                set counter to counter + 1
                if leadingZeros > 0 then set counter to text -(leadingZeros + 1) thru -1 of ("000000" & counter)
                set newName to theName & separator & counter & theExtension
            end repeat
        end tell

        return newName
    end getUniqueName

end script

tell Hazel to try -- test example
    set its sourceFolder to (((path to desktop folder) as text) & "Beautiful Cats:Junior the Cat-1") as alias -- theFile
    set its attributes to "@juniorcat" -- inputAttributes
    run -- do it
    # return whatever
on error errmess -- oops
    tell application "System Events" to display alert "Hazel embedded script error" message errmess
end try

EDIT

Updated to use a script object for Hazel's embedded script.

5
  • red_menace THANK YOU!!! After days of working on this on my own I finally got it working thanks to you. I was using a renaming script I found on github (gist.github.com/oliveratgithub/b9030365c9ae483984ea). For some reason it was not working with renaming the items I move into the old folder. I will make sure to visit your website at menace-enterprises.com where you have tons of useful scripts.
    – David
    Dec 16 '19 at 23:57
  • red_menace, One last request. How do I make the numerical suffix to always start with 1 (Junior the Cat 1.jpg) instead of just the name with no number (Junior the Cat.jpg)?
    – David
    Dec 17 '19 at 0:30
  • @David Somehow I knew you were going to ask that. The handler is set up to be tweaked, so I've updated it to include that option (the posted script will always include a suffix).
    – red_menace
    Dec 17 '19 at 1:32
  • Thanks again red_menace. My only issue now is embedding it into Hazel which for some reason it is not being accepted by embedded script editor. I guess I will need to contact the developer to see what the problem is.
    – David
    Dec 17 '19 at 1:45
  • I had time for a closer look at Hazel, and although an embedded script can't contain handlers (since it apparently is a handler), it can contain script objects. A (regular) script with its own properties and handlers can be developed and tested, then encapsulated in a script object, where its properties can be set and it can be run (or its handlers called) like any other. I've updated my answer to include that.
    – red_menace
    Dec 25 '19 at 0:54

Not the answer you're looking for? Browse other questions tagged .