'on open' is fired twice. Does macOS split dragged files into groups?

Here is a AppleScript to open files from Finder in Vim. Personally, I use Helix command-line editor (hx), but you can replace it with vim, it doesn’t matter.

on run
	tell application "Terminal"
		do script "hx"
		activate
	end tell
end run

on open theFiles
	set fileList to ""
	repeat with aFile in theFiles
		set filePath to POSIX path of aFile
		set fileList to fileList & space & quoted form of filePath
	end repeat
	tell application "Terminal"
		do script "hx" & fileList
		activate
	end tell
end open

Sometimes when I drag multiple files, say 4, on the app’s icon, everything is fine. A single Terminal window appears with 4 Helix buffers.

But sometimes it works weird. There are multiple Terminal window appear, and some buffers are in one window, whereas other buffers are in another window.

I aksed ChatGPT, DeepSeek and Claude, and they say this is because macOS often split dragged files into groups, which means on open handler is fired twice. But is this true? The so-called AI ofter say misleading things.

And how to workaround this, in a concise and beautiful way?

A side note. I’m not sure, but it seems the splitting is somehow related to date-created. I have three identical txt files with the same permissions, and the only difference between them is date-creation. The files are 2022.txt, 2024.txt, and 2025.txt. If I drag all of them at once, 2022 and 2024 are opened together, but 2025 is opened in another Terminal window, even if I drag not three but just two files, e.g. 2022 and 2025.

Here is DMG with them:

test/files.dmg at main · johnmapeson/test · GitHub

(I use DMG and not ZIP or TAR because it’s the only way I know to preserve date creation.)

Yes it’s true.

A work-around is a stay-open script application that adds the open-files to a list on each “on open”, and then process them from an “on idle”

What does your shell script “hx” do?
Also shouldn’t there be a space after the hx like so "do script “hx " & fileList”

or try this…

on run
	tell application "Terminal"
		activate
		if exists window 1 then
			do script "hx" in window 1
		else
			do script "hx"
		end if
	end tell
end run

on open theFiles
	set fileList to ""
	repeat with aFile in theFiles
		set filePath to POSIX path of aFile
		set fileList to fileList & space & quoted form of filePath
	end repeat
	tell application "Terminal"
		activate
		if exists window 1 then
			do script "hx " & fileList in window 1
		else
			do script "hx " & fileList
		end if
	end tell
end open

Make sure its a stay-open app or the second “on open” won’t execute

1 Like

I used nano instead of vim. However, I also did try the same code with vim. There was no need to set this as a stay-open application. I duplicated your files in the .dmg four different times making a total of 12 text files. I then dragged those 12 files onto the app’s Icon and they all opened in the chosen editor in the specified tab or window. I did not experience multiple instances of the on open command launching.

on run
	tell application "Terminal"
		activate
		do script "nano" in front window --> This opens in first tab of multi-tabbed or single open window 
	end tell
end run

on open theFiles
	set fileList to ""
	repeat with aFile in theFiles
		set filePath to POSIX path of aFile
		set fileList to fileList & space & quoted form of filePath
	end repeat
	tell application "Terminal"
		activate
		do script "nano" & fileList in tab 1 of window 6 --> I have one Terminal window with 7 tabs.. This opens in tab 6 of that window 
		-- do script "nano" & fileList in front window --> This would open in first tab of multi-tabbed window or in just window 1 with no other open tabs 
	end tell
end open
1 Like

No, unfortunately this doesn’t solve the issue. This macOS bug/quirk is hard to spot: I just tried to download my own DMG and the files are opened fine. But when I try their original versions on my disk, the bug persists. I decided to simply deal with it.

Out of curiosity, why have the explicit run handler in the first place? Why not put the relevant code inside the open handler just below the activate line.

Oh, by the way, this doesn’t help with storing a bunch of files as a single entity but using rsync -N will maintain the creation time. Of course, depending upon where you would be relocating the files, there may be other issues at play.

Out of curiosity, why have the explicit run handler in the first place? Why not put the relevant code inside the open handler just below the activate line.

Could you show what you mean? Then it will be easier to answer.

As others have already mentioned, it’s indeed a longstanding bug. I don’t have an AppleScript solution for this though, sorry. In Objective-C, there’s a convoluted workaround that I’ve been using for quite a few years.

1 Like

The following code works correctly on Sequoia v15.4.1 and in my case, the Sublime Text 4 (4192) editor. It opens the dropped text files in separate tabs as one would expect. Replace subl with your hx editor.

It gets the dropped items from the NSPasteboardNameDrag clipboard before Applescript can lose its mind about the individual dropped items on the application, and then passes this list onto the on open clause.

use AppleScript version "2.4" -- Yosemite (10.10) or later
use framework "Foundation"
use scripting additions

property NSPasteboard : a reference to current application's NSPasteboard
property NSURL : a reference to current application's NSURL

on run
	# get the dragged files and folders off of the dragged items clipboard *before* we get to the droplet
	set pbdrag to NSPasteboard's pasteboardWithName:(current application's NSPasteboardNameDrag)
	if pbdrag's type {}'s containsObject:(current application's NSPasteboardTypeFileURL) then
		set these_items to (pbdrag's readObjectsForClasses:{NSURL's class} options:(missing value)) as list
	end if
	if these_items = {} then return
	open these_items
end run

on open these_items
	(*
	display dialog (count of these_items) as text
	set {TID, AppleScript's text item delimiters} to {AppleScript's text item delimiters, return}
	display dialog (items of these_items) as text
	set AppleScript's text item delimiters to TID
	*)
	set fileList to {}
	repeat with aFile in these_items
		copy (POSIX path of aFile)'s quoted form & space to the end of fileList
	end repeat
	tell application "Terminal"
		activate
		if exists window 1 then
			# subl is my shell alias for sublime text 4
			do script "subl " & fileList in window 1
		else
			do script "subl " & fileList
		end if
	end tell
	return
end open