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
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.
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.
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}
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 :
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.
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
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. 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
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 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")
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
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.
set pngFilesAsString to (do shell script "ls -1 \"" & folderPath & "\" | grep -i '\\.pdf$' | sort -V")
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.
@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.
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.