You can make a difference in the Apple Support Community!

When you sign up with your Apple Account, you can provide valuable feedback to other community members by upvoting helpful replies and User Tips.

Looks like no one’s replied in a while. To start the conversation again, simply ask a new question.

JS/AS Automation version of Automator's Ask for Finder Items: Files and Folders

I want to script this. I know how to do app.chooseFolder or app.chooseFile (w/multiple selection), but that's either/or. Drag and drop as well as the Ask for Finder Items Automator action allow selecting either Files or Folders or a combination of both.. If there's an Applescript version I should be able to convert to the JS equivalent.




Posted on May 10, 2020 7:26 AM

Reply
Question marked as Top-ranking reply

Posted on May 16, 2020 4:47 AM

I think I have written about five JXA scripts since it was introduced, and will have to pass on debugging any JXA code. The non-JXA solutions that I provided previously were tested and return their selected content. I have not tested what the ramifications of running JXA code in an Automator Run AppleScript action might produce.


You cannot assume that AppleScript (and potentially JXA code) saved as an application from Script Editor, or from Automator using a Run AppleScript action — will work identically, because the AppleScript runtime engine is different between them. This may or may not have an impact on JXA results.

10 replies
Question marked as Top-ranking reply

May 16, 2020 4:47 AM in response to agent101

I think I have written about five JXA scripts since it was introduced, and will have to pass on debugging any JXA code. The non-JXA solutions that I provided previously were tested and return their selected content. I have not tested what the ramifications of running JXA code in an Automator Run AppleScript action might produce.


You cannot assume that AppleScript (and potentially JXA code) saved as an application from Script Editor, or from Automator using a Run AppleScript action — will work identically, because the AppleScript runtime engine is different between them. This may or may not have an impact on JXA results.

May 15, 2020 3:09 PM in response to VikingOSX

I did a variation, but my drag and drop has odd behavior. I often get a partial list of the files/folders. Once Cancel or Ok is pressed, I get more (not always all). If the files are the same type/ext, this does not seem to happen.

The bare bones script below saved as an app has the same drag and drop issue. Thoughts?

Reference:

https://developer.apple.com/library/archive/documentation/LanguagesUtilities/Conceptual/MacAutomationScriptingGuide/ProcessDroppedFilesandFolders.html#//apple_ref/doc/uid/TP40016239-CH53-SW1


var app = Application.currentApplication()
app.includeStandardAdditions = true
//openDocuments in JS same as "on open" in AS. save as app.
function openDocuments(droppedItems) {
	app.displayDialog(`${droppedItems}`);
}



May 10, 2020 2:12 PM in response to agent101

Another approach is to save an Automator workflow where you can find it in your path.



And then run that workflow in ASOC sending the starting folder path to be captured by the first action.


use framework "Foundation"
use framework "Automator"
use AppleScript version "2.4" -- Yosemite or later
use scripting additions

property NSString : a reference to current application's NSString
property NSURL : a reference to current application's NSURL
property AMWorkflow : a reference to current application's AMWorkflow

set alist to {}
set wfpath to "~/bin/AskForFilesFolders.workflow"
set stpath to "~/Documents"

set alist to my files_and_folders(wfpath, stpath)
if alist contains "None Selected" then display dialog alist as text

set {TID, AppleScript's text item delimiters} to {AppleScript's text item delimiters, return}
display dialog (items of alist) as text with title "Automator Chooser Results"
set AppleScript's text item delimiters to TID
return

on files_and_folders(aworkflow, startdir)
	-- Open a chooser that allows n-tuple files/folder selection at the startdir
	set workflow_path to (NSString's stringWithString:aworkflow)'s stringByExpandingTildeInPath()
	set workflowURL to NSURL's fileURLWithPath:workflow_path
	set start_path to (NSString's stringWithString:startdir)'s stringByExpandingTildeInPath()
	set newlist to {}
	
	set {theResult, theError} to AMWorkflow's runWorkflowAtURL:workflowURL withInput:(start_path as text) |error|:(reference)
	
	-- eliminate starting folder entry if user only clicked "Choose"
	if ((theResult = {}) is true) then return "None Selected"
	
	repeat with e in theResult
		if (e as text) is equal to (start_path as text) then
			log "skipping"
		else
			copy (e as text) to the end of newlist
		end if
	end repeat
	
	if not (newlist = {}) is true then
		return newlist as list
	else
		return "None Selected"
	end if
	
	if theError is not missing value then
		display dialog (theError's localizedDescription()) as text
	end if
	return
end files_and_folders


Tweak to need.

May 10, 2020 8:27 AM in response to agent101

Here is a two-part ASOC script that simulates Automator's Ask for Finder Items action. Because this hosting software inane 5000 character limit, I must post it in two parts, which when appended give you a solution. To run the script directly from Script Editor, press the control+command+R keys, though this would not be required when in an application. I wrote this a few years back, and it still works on Mojave 10.14.6. I would likely write it differently today.


Part 1


use framework "AppKit"
use AppleScript version "2.4" -- Yosemite or later
use scripting additions

-- File chooser that can return POSIX or HFS file formats based on the
-- POSIX or HFS argument to the files_follders handler.

property default_loc : "~/Desktop"
property file_types : {"com.apple.iWork.pages.pages", ¬
	"com.apple.iWork.pages.sffpages", ¬
	"org.openxmlformats.wordprocessingml.document", ¬
	"com.microsoft.word.doc", "public.folder"}
property HFS : "HFS"
property POSIX : "POSIX"

on run
	-- check we are running in foreground
	if not (current application's NSThread's isMainThread()) as boolean then
		display alert "This script must be run from the main thread." buttons {"Cancel"} as critical
		error number -128
	end if
	
	set openstuff to files_folders(POSIX) as list
	-- set openstuff to files_folders(HFS) as list
	log openstuff
	return
	
end run


May 10, 2020 8:26 AM in response to VikingOSX

Part 2


on files_folders(afmt)
	
	set returnCode to 0 as integer
	if default_loc starts with "~" or adir starts with "../" then
		-- relative POSIX paths to standard paths conversion
		set tpath to current application's NSString's stringWithString:default_loc
		set stdpath to tpath's stringByStandardizingPath() as text
	end if
	-- custom file chooser
	set oPanel to current application's NSOpenPanel's openPanel()
	tell oPanel
		its setFloatingPanel:true -- over the top of all other windows
		its setDirectoryURL:(POSIX file stdpath)
		its setFrame:(current application's NSMakeRect(0, 0, 720, 525)) display:yes
		its setTitle:"Open"
		its setMessage:"Select file(s) and/or folder(s) with ⌘"
		its setPrompt:"Select"
		
		its setAllowsMultipleSelection:true
		its setAllowedFileTypes:file_types
		its setCanChooseFiles:true
		its setCanChooseDirectories:true
		its setTreatsFilePackagesAsDirectories:false
	end tell
	
	set returnCode to oPanel's runModal()
	if returnCode is (current application's NSFileHandlingPanelCancelButton) then
		error number -128
	end if
	-- set the POSIXpaths to (oPanel's |URL|()'s valueForKey:"path") as list
	if afmt is "HFS" then
		return (oPanel's URLs) as list
	else if afmt is "POSIX" then
		return (oPanel's filenames()) as list
	else
		-- neither is not an option, force user cancel
		error number -128
	end if
	return
	
end files_folders


May 10, 2020 7:40 PM in response to agent101

And finally, building on the saved Automator Workflow that I named AskForFilesFolders.workflow, setting the Path automator variable, and returning selected files and folders as POSIX path list items:


set start_folder to "$HOME/Documents"
set alist to paragraphs of (do shell script "automator -D Path=" & start_folder & " $HOME/bin/AskForFilesFolders.workflow  2> /dev/null | ~/trmdls.awk")

-- expand the start_folder to absolute path
set abspath to (do shell script "printf '%s' " & start_folder)

-- test if alist was cancelled (empty) or same string as start_folder
-- because user clicked choose without a selection
if alist = {} or (alist as text) is equal to abspath then
	log "User cancellation, or choose without selection."
	return
else
	log alist
end if
return



The trmdls.awk script is also something that I use to clean up the returned content from mdls too. This content does not go into the Script Editor but any decent text editor. Also, make it executable after you save it:


chmod +x ./trmdls.awk


trmdls.awk


#!/usr/bin/awk -f
#
# trmdls.awk
# Usage: mdls -name kMDItemFonts filename | trmdls.awk

# 1) one line to process. Print entire third field
NR == 1 && !/\(/ {print substr($0, index($0,$3))}

# 2) multiple lines. Skip first and last lines containing '(' and ')'
#    Remove quotes and trailing ",". Remove leading/trailing whitespace,
NR > 2 {print l} {$1=$1}1 {gsub(/,$/, "");gsub(/"/, "");l=$0}
END {exit}



JS/AS Automation version of Automator's Ask for Finder Items: Files and Folders

Welcome to Apple Support Community
A forum where Apple customers help each other with their products. Get started with your Apple Account.