AppleScript: image attachments to a Note mysteriously appear twice

A newbie with AppleScript and mostly debugging chat-gpt recommended code, but I cannot figure out why are the images which I’m attaching to a new note all seem to appear twice. The script iterates through a selected folder’s files, and for each one it logs once the name of the file and then adds it as an attachment to the new note. The Notes app reports the correct number of attachment under its title in the middle column listing the notes in a folder. But when I click to see the newly created note, I see the first image twice, then the second image twice, then the third image twice etc…

Any idea why this is happening?
Thank you!

-- Define the folder containing PNG images
set folderPath to POSIX path of (choose folder with prompt "Select the folder containing PNG images")

-- Get the folder name to use as the note title
set folderName to name of (info for folderPath)

-- Get a list of PNG files in the folder
set pngFiles to paragraphs of (do shell script "ls -1 \"" & folderPath & "\" | grep -i '.png'")

set pngFilesAsString to ""
repeat with eachFile in pngFiles
	set pngFilesAsString to pngFilesAsString & eachFile & return
end repeat
log "Current pngFiles: " & pngFilesAsString

do shell script "echo \"" & (quoted form of (pngFilesAsString)) & "\" >> /Users/doulos/logfile.txt"


-- Sort the list of PNG files in increasing order
set sortedPngFiles to paragraphs of (do shell script "echo \"" & pngFilesAsString & "\" | sort -V")
--do shell script "echo \"" & (quoted form of (sortedPngFiles)) & "\" >> /Users/doulos/logfile.txt"
log "sortedPngFiles: " & sortedPngFiles


-- Create a new note in the Notes app
tell application "Notes"
	set newNote to make new note with properties {name:folderName}
end tell

-- Add each PNG file to the note
repeat with fileName in sortedPngFiles
	
	-- do shell script "echo \"" & (quoted form of (fileName)) & "\" >> /Users/doulos/logfile.txt"
	log "Current fileName: " & fileName
	-- Create a new note in the Notes app
	tell application "Notes"
		set theFile to (folderPath & fileName) as POSIX file
		make new attachment of newNote with data theFile
		save
	end tell
	
end repeat

Hi @jackdumpster. Welcome to MacScripter.

I see the effect you’re describing, but only with large images. I think it’s some peculiarity of Notes when the images are redrawn during scrolling. They don’t seem to be actually duplicated in the note itself.

If you’re interested, I’ve reworked the script a little to reduce the number of shell scripts and to correct a couple of minor things in the attachment-adding repeat.

-- Define the folder containing PNG images
set folderPath to POSIX path of (choose folder with prompt "Select the folder containing PNG images")

-- Get the folder name to use as the note title
set folderName to name of (info for folderPath)

-- Get a sorted list of PNG files in the folder. (They're probably sorted anyway).
set pngFilesAsString to (do shell script "ls -1 \"" & folderPath & "\" | grep -i '.png' | sort -V")
log "Current pngFiles: " & pngFilesAsString
do shell script "echo " & (quoted form of (pngFilesAsString)) & " >> /Users/doulos/logfile.txt"

set sortedPngFiles to paragraphs of pngFilesAsString

-- Create a new note in the Notes app
tell application "Notes"
	activate
	set newNote to make new note at account "On My Mac" with properties {name:folderName}
	
	-- Add each PNG file to the note
	repeat with fileName in sortedPngFiles
		log "Current fileName: " & fileName
		-- Create a new note in the Notes app
		set theFile to (folderPath & fileName) as POSIX file
		make new attachment at newNote with data theFile
	end repeat
end tell

I tested Nigel’s suggestion, and it worked fine, but the note contained duplicate images (as expected). I don’t know why that is.

The shortcut included below does not create duplicate images and might be considered if the OP is running macOS Monterey or newer. The user needs to set the target Notes folder in the shortcut’s Create Note action.

Images to Note.shortcut (23.1 KB)

Both of you thank you so much @Nigel_Garvey and @peavine Thank you so much, your solutions are both much better improvement, the first one is simpler , more readable code, the second one is actually solving completely my problem because there’s no manual involvement from me to deduplicate the slides afterwards, it looks like there’s zero issues on my MacBook (on Sonoma) with the proposed shortcuts. I’m actually a complete newbie to Shortcuts as well, I had no idea this even existed, and was wondering what happened recently when I saw a Microsoft similar automation tool, which I thought from the video it was super easy to scape a website (the demo) and thought to myself… “I wish we had a similar easy tool like that on the Mac”… This Shortcuts tool seems to be super!!! Thank you again both!

@peavine do you know if there’s a way to create a droplet instead of manually selecting the folder at the very first step? It’d probably be easier if I just drag and drop a folder onto an icon of the shortcut, I already saw that I can place a shortcut icon on the launch bar and maybe I can place one on the desktop and emulate the “on open(droppedFolder)” functionality of AppleScript …

Also, can you show me with another screenshot how to parse the first 4 characters of the chosen or dropped folder and then place the newly created Note into the Notes.app folder with folder-name equal to those 4 characters. Say the 4 first characters of the droplet’s folder signify countries, and I want automatically the new Note to be placed not randomly inside Notes.app, but placed inside the country folder of Notes.app (On my Mac account is preferred). I’m just going by equivalent functionality in AppleScript, except I’m loving Shortcuts for its user friendliness. I’ll keep digging myself as well…

jackddumpster. The Shortcuts app doesn’t support droplets. One alternative is to use the Get Selected Files in Finder action (which works with folders). You would select the target folder in a Finder window and then run the shortcut by way of 1) the Shortcuts Menu, 2) an icon in the Dock, 3) an icon in the Finder toolbar, 4) a keyboard shortcut, or 5) the Finder Services menu.

As regards your second question, I don’t know a good solution. The shortcut included below does exactly what you want the first time it is run on a folder but appends a counter to the Notes folder the second time the shortcut is run on a folder. So, if the target folder is Testing, the Notes folders are Test, then Test 1, then Test 2, and so on. I assume this is not how you want the shortcut to work; I’ll give this some additional thought.

Images to Note.shortcut (23.7 KB)

jackddumpster. The only way I can see to do what you want is to use an AppleScript to create the Notes folder and a shortcut to create the note. The AppleScript prompts the user for the target folder, but it’s easily made into a droplet. I tested this on my Sonoma computer, and everything worked as desired.

The AppleScript:

set theFolder to (choose folder with prompt "Select the folder containing PNG images")

tell application "Finder"
	set theFiles to (every file in theFolder whose name extension is "png") as alias list
	set folderName to name of theFolder
end tell

if (count theFiles) is 0 then display dialog "PNG file not found" buttons {"OK"} cancel button 1 default button 1
set shortFolderName to text 1 thru 4 of folderName

tell application "Notes"
	activate
	if not (exists folder shortFolderName) then make new folder with properties {name:shortFolderName}
end tell

tell application "Shortcuts Events" to run shortcut named "Make Note" with input {folderName, shortFolderName, theFiles}

The Shortcut:

Make Note.shortcut (22.4 KB)

Hi @peavine , yes I found a similar approach, but I like your last line tell application “shortcuts events” better. You can make a droplet with AppleScript that accepts and gets activated by the usual means and that applies the usual code section between :

on open(droppedFolder)

end open

Inside there you can place either your very simple statement which I didn’t know, or a shell script command using Run shortcuts from the command line - Apple Support.

then you can also create a shortcuts recipe similar to the gallery ones that accepts Shortcut Input instead of the select via GUI a folder.

Alternatively, similar to the above exact solution, we can implement a Hot Folder instead where we drag and drop the files/folders needing processing, instead of dragging & dropping them on the droplet icon. Then the shortcut recipe can just hardcode the hot folder to look for input there always instead of accepting it as input.

1 Like

jackddumpster. I agree that the Shortcuts Events run command can be very useful. At first, I had reservations over mixing AppleScripts and shortcuts, but I’ve come to accept that they can do useful stuff and that’s a good thing.

FWIW, I tested to see if my AppleScript in post 7 would work if rewritten with an on open handler. Fortunately, it worked as hoped (although setting permissions remains a continuing issue):

on open theFolder
	set theFolder to item 1 of theFolder
	
	tell application "Finder"
		set theFiles to (every file in theFolder whose name extension is "png") as alias list
		set folderName to name of theFolder
	end tell
	
	if (count theFiles) is 0 then display dialog "PNG file not found" buttons {"OK"} cancel button 1 default button 1
	set shortFolderName to text 1 thru 4 of folderName
	
	tell application "Notes"
		activate
		if not (exists folder shortFolderName) then make new folder with properties {name:shortFolderName}
	end tell
	
	tell application "Shortcuts Events" to run shortcut named "Make Note" with input {folderName, shortFolderName, theFiles}
end open

Hi,
In the current version of Notes, the “make new attachment” command actually creates two image attachments. However, they have the same ID.
This is why Notes shows in the overview that only one attachment exists.

tell application "Notes"
	set sel to selection
	set sel to item 1 of sel
	set noteID to «class seld» of (sel as record)
	tell note id noteID
		set theAttachments to attachments's id
	end tell
end tell

Two attachments means that the preview of the attachment is also shown twice in the body of the note.
Since @Nigel_Garvey wrote that this only happens with larger images, you can delete an attachment if it exists twice. Add something like this to his script:

		tell newNote
			-- 1 image only added:	if (count of attachments) is 2 then delete attachment 2
			-- else:
			set theAttachments to attachments's id
			set nodupes to {}
			repeat with i from 1 to count of theAttachments
				set x to (theAttachments's item i)
				if x is not in nodupes then
					set end of nodupes to x
				else
					delete attachment i
				end if
			end repeat
		end tell

1 Like

Keita beat me to it by a few minutes!

The reason I wasn’t seeing two copies of each image above was that I neglectfully tested the script with Notes 4.10 on my Ventura machine instead of with Notes 4.11 on the Sonoma one. Sorry about that. :slightly_frowning_face: In fact the attachments are duplicated in Ventura too, but my images are only shown once each in the note — although with large gaps between them. The solution is, as Keita’s said, to delete the duplicates if they exist. It improves the display in Ventura too. The way I’ve done it is to compare the number of attachments at each stage with the number expected.

-- Define the folder containing PNG images
set theFolder to (choose folder with prompt "Select the folder containing PNG images")
set folderPath to theFolder's POSIX path

-- Get the folder name to use as the note title
tell application "System Events" to set folderName to theFolder's name

-- Get a sorted list of PNG files in the folder. (They're probably sorted anyway).
set pngFilesAsString to (do shell script "ls -1 \"" & folderPath & "\" | grep -i '.png' | sort -V")
log "Current pngFiles: " & pngFilesAsString
do shell script "echo " & (quoted form of (pngFilesAsString)) & " >> /Users/doulos/logfile.txt"

set sortedPngFiles to paragraphs of pngFilesAsString
set attachmentsAdded to 0

-- Create a new note in the Notes app
tell application "Notes"
	activate
	set newNote to make new note at account "On My Mac" with properties {name:folderName}
	
	-- Add each PNG file to the note
	repeat with fileName in sortedPngFiles
		log "Current fileName: " & fileName
		-- Create a new note in the Notes app
		set theFile to (folderPath & fileName) as POSIX file
		tell newNote
			make new attachment with data theFile
			set attachmentsAdded to attachmentsAdded + 1
			-- A bug in Notes 4.10 and 4.11 (or in macOS 13 and 14) 
			-- causes the attachment to be added twice. Delete the duplicate.
			if ((count attachments) > attachmentsAdded) then delete last attachment
		end tell
	end repeat
end tell
1 Like

Thank you both @Nigel_Garvey and @Keita !

I tried Nigel’s and it worked flawlessly !

Strange thing: taking Nigel’s code above and simply replacing .png with .pdf in the shell script line that selects the actual files I want to attach, gives duplicate pdf attachments. I had an original slide-deck in .pdf, and I can generate .png images or .pdf pages (I split the deck-pdf into pdf-pages with a shortcut recipe I made, I don’t know how to do that in AppleScript outside invoking a shell script, and looked for the dictionary for Preview but no split command. BTW, do you guys know if there’s a native or simple way to split a PDF file into separate pdfs for all its pages, in AppleScript ? admittedly mixing AppleScript and shortcuts doesn’t feel as good for me, and I seem to have a better control of AppleScript because of variables etc I can refer to explicitly in my code vs. figuring out the GUI of Shortcuts ).

Any rate, Nigel’s concise script doesn’t seem to depend on the type of attachments I put on the new note, maybe you guys have a clue about why it still duplicates PDF pages though?

I ran your hint/script on a new Note that contains duplicate pdf attachments and it comes back with empty
{ }

Running the same script on a new Note that contains the png attachments shows me some things like:

{“x-coredata://20ABA9F3-1B2E-4EBE-8E41-F1C9D98D4F67/ICAttachment/p919941”, “x-coredata://20ABA9F3-1B2E-4EBE-8E41-F1C9D98D4F67/ICAttachment/p919945”, "x-coredata:// …

Not sure if that tells you guys anything, I’m completely newbie, last week I knew nothing about appleScript

I don’t believe you can split a PDF into separate pages with basic AppleScript alone. The following will do this, but obviously it’s not particularly simple. The other alternative is a shortcut, which is simple but not an AppleScript.

use framework "Foundation"
use framework "PDFKit"
use scripting additions

set sourcePDF to POSIX path of (choose file of type {"pdf"})
splitPDF(sourcePDF)

on splitPDF(sourcePDF) -- based on handler written by Shane Stanley
	set sourcePDF to current application's |NSURL|'s fileURLWithPath:sourcePDF
	set sourcePDFName to sourcePDF's lastPathComponent()
	set destinationFolder to sourcePDF's URLByDeletingLastPathComponent
	set sourceDocument to current application's PDFDocument's alloc()'s initWithURL:sourcePDF
	set sourcePageBounds to (sourceDocument's pageAtIndex:0)'s boundsForBox:(current application's kPDFDisplayBoxMediaBox)
	set sourcePageCount to sourceDocument's pageCount() as integer
	repeat with i from 1 to sourcePageCount
		set theFileNameNoExtension to sourcePDFName's stringByDeletingPathExtension()
		set theExtension to sourcePDFName's pathExtension()
		set targetPDFName to ((theFileNameNoExtension's stringByAppendingString:("-" & i))'s stringByAppendingPathExtension:theExtension)
		set targetPDF to (destinationFolder's URLByAppendingPathComponent:targetPDFName)
		set thePDFPage to (sourceDocument's pageAtIndex:(i - 1))
		(thePDFPage's setBounds:sourcePageBounds forBox:(current application's kPDFDisplayBoxMediaBox))
		set targetDocument to current application's PDFDocument's new()
		(targetDocument's insertPage:thePDFPage atIndex:0)
		(targetDocument's writeToURL:targetPDF)
	end repeat
end splitPDF

I used something similar asking ChatGPT and replacing a command, which is a bit simpler:

on splitPDF(inputFilePath, outputFolderPath)
	-- Check if input file exists
	if (not (exists POSIX file inputFilePath as alias)) then
		display alert "Input file does not exist!" message "The file path provided does not exist." as warning
		return
	end if
	
	-- Check if output folder exists, create if not
	if (do shell script "[ -d " & quoted form of outputFolderPath & " ] && echo 'exists' || echo 'not found'") is not "exists" then
		do shell script "mkdir -p " & quoted form of outputFolderPath
	end if
	
	-- Split PDF into pages using pdfseparate
	set outputPath to quoted form of POSIX path of outputFolderPath
	set inputPath to quoted form of POSIX path of inputFilePath
	set command to "/opt/homebrew/bin/pdfseparate " & inputPath & " " & outputPath & "/page_%04d.pdf"
	try
		do shell script command
		display alert "PDF successfully split!" message "The PDF has been split into individual pages." as informational
	on error errMsg
		display alert "Error splitting PDF" message errMsg as warning
	end try
end splitPDF

splitPDF("/path/to/originalFile.pdf", "/output/folder")

@Nigel_Garvey @Keita

I’m giving up, I tried everything, but Nigel’s code is super simple and replacing .png with .pdf in the grep command should work without creating duplicate attachments for .pdf but not for .png, this seems crazy.

Here’s the exact code I used:

-- Define the folder containing PNG images
set theFolder to (choose folder with prompt "Select the folder containing PNG images")
set folderPath to theFolder's POSIX path

-- Get the folder name to use as the note title
tell application "System Events" to set folderName to theFolder's name

-- Get a sorted list of PNG files in the folder. (They're probably sorted anyway).
set pngFilesAsString to (do shell script "ls -1 \"" & folderPath & "\" | grep -i '.pdf' | sort -V")
log "Current pngFiles: " & pngFilesAsString
do shell script "echo " & (quoted form of (pngFilesAsString)) & " >> /Users/doulos/logfile.txt"

set sortedPngFiles to paragraphs of pngFilesAsString
set attachmentsAdded to 0

-- Create a new note in the Notes app
tell application "Notes"
	activate
	set newNote to make new note at account "On My Mac" with properties {name:folderName}
	
	-- Add each PNG file to the note
	repeat with fileName in sortedPngFiles
		log "Current fileName: " & fileName
		-- Create a new note in the Notes app
		set theFile to (folderPath & fileName) as POSIX file
		tell newNote
			make new attachment with data theFile
			set attachmentsAdded to attachmentsAdded + 1
			-- A bug in Notes 4.10 and 4.11 (or in macOS 13 and 14) 
			-- causes the attachment to be added twice. Delete the duplicate.
			if ((count attachments) > attachmentsAdded) then delete last attachment
		end tell
	end repeat
end tell

Any ideas? The only thing I can think of is perhaps a race condition between the
make new attachment with data theFile

which has not yet completed (it does seems somewhat slow on my Notes.app with thousands of notes in it)

and the statement that removes duplicates after checking the condition:

if ((count attachments) > attachmentsAdded) then delete last attachment

which clearly doesn’t actually succeed in removing any duplicate pdf attachments because I end up seeing them in the resulting note. Maybe it’s faster to register .png attachments to the attachments property of newNote?

Either way I don’t know how to force syncing of the note (eg. a save is not supported) to make sure the latter if statement would correctly count the attachments…

I’m hoping maybe these give you guys some hint, I feel like I don’t know the basics

Hi jackddumpster.

My initial observation on checking this out is that it also happens with PDFs on my Sonoma machine, but not on the Ventura one. It turns out that in Sonoma (or Notes 4.11, whichever’s to blame), PDF attachments don’t register when when a script asks the note what attachments it has — as I see you’ve already noted above. So a script can’t tell if those attachments are duplicated. And just telling the note to delete them anyway doesn’t work either. I can’t see a way round this at the moment, but I’ll do some more looking this morning.

Actually, one of AppleScript’s main design features is to be mixable with whatever gets a job done or whatever the user feels comfortable using. Your shell scripts aren’t AppleScript, for example, but the do shell script command makes their use with AppleScript possible. The fact that Apple has produced an AppleScriptable application to run shortcuts, long after it apparently lost interest in AppleScript itself, seems quite encouraging….

Later: No luck with a workaround, I’m afraid. The make command for the attachments returns attachment specifiers, but even these aren’t recognised by Notes when the attachments are PDFs, nor is there anything in the note’s body HTML to indicate the attachments exist.

An unrelated script weakness which did come to light by accident is that the grep part of the shell script needs tightening up to ensure that the dot actually matches a dot and the pattern matches the end of the path. :slightly_smiling_face:

set pngFilesAsString to (do shell script "ls -1 \"" & folderPath & "\" | grep -i '\\.pdf$' | sort -V")
1 Like

I’ve included below a shortcut that adds all PDFs in a selected folder to a note. As written, it splits multi-page PDFs into individual pages and adds all of them to the note. The shortcut is easily modified to only add the first page of each PDF if that’s desired. I successfully tested this shortcut on my Sonoma computer with multi-page PDFs that contained images, multi-page PDFs that contained one to four pages of Shane’s ASObjC book, and a combination of these.

PDF to Note.shortcut (23.6 KB)

@peavine @Nigel_Garvey This is a perfectly fine recipe for solving a small version of the problem (where the original pdf has at most ~100 pages ie. about the max # of attachments per note, and I have something very similar as a last resort, I was just hoping to do it in scripting only (AppleScript + bash) so that I can do string manipulation much quicker than GUI. I may still have to resort to the GUI solution as a sub-module I have to invoke, it looks like…

Thank you both for your assistance, can I mark both your responses as solutions? I’m happy to, and just realized that I’m supposed to do that, a complete newbie and I apologize.

Sorry for my late reply.

And while I was writing my post, I realised that you @Nigel_Garvey could do a much better job of implementing my script suggestion. Great! And thank you for sharing your knowledge!

Here is what I found out….

It’s extremely weird: Using the search function in the notes app, I find all notes with attached PDFs.

If I then use a script to get attachments or properties of an older note that I haven’t opened for a while, without selecting it directly in the Notes app (!), the PDF attachment is displayed correctly. However, as soon as I select this note and start the script again, no attachment is found.

tell application "Notes"
	tell note "Xyz" -- name of the note
		attachments
		--properties
	end tell
end tell

So the script I posted does not find PDF attachments because the note was previously selected.
I suspect this is related to changes in the Notes application database, but that doesn’t help either.