I would like to create an Applescript that mimics the behavior of an alias to a specific folder X. If files are dragged to it, they should be moved to folder X, but if the Applescript is just double-clicked, folder X should be opened.
I am an Applescript novice, but adapting things I've found on the web, I have constructed working pieces: one that moves dragged files to X and one that opens X. I do not know enough to combine them with "if...else" logic, so that if nothing is dragged, the folder is opened; but if things are dragged, they are moved to X but X is not opened.
repeat with a from 1 to length of theDroppedItems
set theCurrentDroppedItem to item a of theDroppedItems
tell application "Finder"
set folderMyFolder to folder "/Users/myname/myfolder"
move theCurrentDroppedItem to folderMyFolder
end tell
end repeat
end open
tell application "Finder" to open "Macintosh HD:Users:myname:myfolder"
When your script contains an open handler, it will be passed items dropped onto the application, while the run handler is the one called when the application is double-clicked. You don't need to do any comparisons, just place the statements to be performed in the appropriate handler, for example:
property targetFolder : ((path to home folder) as text) & "path:to:myfolder"
on run
tell application "Finder" to open folder targetFolder
end run
on open droppedItems
repeat with anItem in droppedItems
tell application "Finder" to move anItem to folder targetFolder
end repeat
end open
Note that the Finder doesn't know about POSIX paths, so to use them you will need to coerce the paths to something the Finder can handle, or use something that does know POSIX paths, such as System Events.
Related
As you can see from my code below I am extremely new to this. My code just about works, but my major issue is that it hogs up Finder and sometimes it does not set the Desktop picture, but does most of the time!
The script just monitors a folder, and if an "***.jpg" is added then the Desktop picture set to it.
This is my very first script so I have a lot to learn,
set reset to ""
display notification "Alarm Front Active " & (current date) as string
tell application "Finder"
set path_to_sourceFull to ":photo:FRONT CAM 1:20190929:images" -- from nsa310 network drive
set path_to_source to ":photo:FRONT CAM 1:20190929:images" -- from nsa310 network drive
set directory1 to "/Volumes/photo/FRONT CAM 1/20190929/images" as text -- from nsa310 network drive
set path_to_destinationFull to "Macintosh HD:Users:rekordbox:Documents:temp folder 2"
set path_to_destination to ":Users:rekordbox:Documents:temp folder 2"
set directory2 to "/Users/rekordbox/Documents/temp folder 2" as text
repeat while reset = ""
set allok to ""
set filelist to name of every item in folder path_to_source --of startup disk
set listSizesaved to count of filelist
delay 1
repeat while allok = ""
set filelist to name of every item in folder path_to_source --of startup disk
set listSize to count of filelist
if listSize = listSizesaved then
else
set filelist to name of every item in folder path_to_source --of startup disk
set listSize to count of filelist
set LastAddedFile to item listSize of filelist
set allok to "ALARM"
set listSizesaved to listSize -- (save the updated) count
set activefile to (path_to_source & LastAddedFile)
set selectedpicture to (directory1 & "/" & LastAddedFile)
tell application "System Events" to tell every desktop to set picture to selectedpicture
delay 1
display notification "ALARM FRONT TRIGGERED...." & (current date) as string
delay 1
end if
end repeat
end repeat
end tell
The script you want, I think, is this:
on adding folder items to thisFolder after receiving filelist
set droppedFile to first item of filelist
tell application "System Events"
tell every desktop
set picture to droppedFile
end tell
end tell
end adding folder items to
(I've left out the 'Alarm' bit, since I wasn't sure what the point of it was.)
To use this script, copy it into Script Editor, save it in the folder ~/Library/Scripts/Folder Action Scripts/, then open the applet 'Folder Actions Setup'. Add the folder you want on the left-hand side, and choose the file you just saved on the right. It should look something like this:
...where the checkmark on the left shows that folder actions are enabled for the folder (which I called 'test folder') and the script (which I called 'FADtop.scpt') is attached.
Drop an image in the folder, and it should just work.
As a general rule, don't script the Finder unless you absolutely need to; always use System Events. The Finder is a busy app, and scripting it can gum up the system. And also try to avoid this design pattern:
(* Don't do this! *)
repeat
(* test for something *)
delay x
end
The delay command is not particularly resource-efficient. If you really want to use a polling system to test for some event, it's often better to create a stand-alone app with an on idle handler. That way you let the system wake and sleep the script, with significant performance improvements.
EDIT
Since folder actions don't seem to be working with ftp drops onto remote drives, here's a reasonably efficient folder-polling approach. Save the following script as a stay-open application (choose 'Application' as the file type, and click the 'stay open' checkbox). Then launch the application and leave it running in the background.
property dateOfLastFileChosen : missing value
property targetFolder : "/Volumes/photo/FRONT CAM 1/20190929/images"
property idleTime : 300 -- 300 seconds is five minutes
on run
end run
on idle
tell application "System Events"
if exists folder targetFolder then
if dateOfLastFileChosen is missing value then
set recentFiles to every file of folder targetFolder whose visible is true
else
set recentFiles to every file of folder targetFolder whose modification date > dateOfLastFileChosen and visible is true
end if
set newFile to my mostRecentFileOfList(recentFiles)
if newFile is not missing value then
set dateOfLastFileChosen to modification date of newFile
tell every desktop
set picture to (POSIX path of newFile)
end tell
end if
end if
end tell
return idleTime -- check every 5 minutes (300 seconds)
end idle
on mostRecentFileOfList(fileList)
set maxDateObj to missing value
repeat with thisFile in fileList
if maxDateObj is missing value then
set maxDateObj to contents of thisFile
else if modification date of thisFile is greater than modification date of maxDateObj then
set maxDateObj to thisFile
end if
end repeat
return maxDateObj
end mostRecentFileOfList
Without trying to steal the thunder from #Ted Wrigley, whose solution provided the AppleScript code for the folder action, I felt there were enough comments and items for me to add to post it as another answer to the OP's dilemma.
First I will address the tell every desktop set picture to droppedFile lines of code in the following AppleScript Folder Action. If the user has only one monitor/display attached to the computer, but has created several different "Spaces", the tell every desktop set picture to droppedFile lines of code will only change the Desktop Picture for the Desktop of the current active "Space" only. The other Desktop backgrounds will not be changed. However, if the user has several monitors/displays attached to the computer, the tell every desktop set picture to droppedFile lines of code will change the Desktop Pictures for the Desktops of the current active "Space" for each attached monitor/display. If the latter is not the desired result, then tell every desktop should be changed to tell current desktop.
After testing the AppleScript Folder Action code provided by #Ted Wrigley, I noticed the image file being downloaded from an FTP server, to the test folder where I have the folder action script attached to, looked like this before the image was actually finished transferring. Because the file was kind of there and not there, it did not trigger the Folder Action.
Next, I figured I would add a delay to be beginning of the Folder Action code to allow for the transfer of the image file from the FTP server, to complete. I added a delay of 180 seconds to allow for the transfer to complete and it worked. When the transfer was complete, the file look like this.
Depending on how many files you foresee being transferred at any given time along with factoring in for file sizes... It's possible you may need to significantly increase the Delay time.
on adding folder items to thisFolder after receiving theseFiles
delay 180
set newBackground to first item of theseFiles
tell application "System Events"
set picture of current desktop to newBackground -- Single Display Attached
--set picture of every desktop to newBackground -- Multiple Displays Attached
end tell
end adding folder items to
I have an Applescript app that can receive files or folders dropped onto its icon:
on open theDroppedItems
tell application "Finder"
set droppedItemSourcePath to (the POSIX path of theDroppedItems)
...
At this point of the script, when my app receives a file or a folder, an unknown and useless Applescript application named "Droplet" displays an open file/folder dialog.
My script was compiled as application with Script Debugger 6.
I don't understand why this strange "Droplet" app asks me something.
The mistake is that theDroppedItems is a list of alias specifiers even if only one file was dropped and getting the POSIX path of a list throws an error
To get all POSIX paths of the dropped items use
on open theDroppedItems
set {TID, text item delimiters} to {text item delimiters, return}
set droppedItemsSourcePaths to POSIX path of (theDroppedItems as text)
set text item delimiters to TID
display dialog droppedItemsSourcePaths buttons {"OK"} default button "OK"
...
To process the files one by one use a loop
on open theDroppedItems
repeat with anItem in theDroppedItems
-- do something with anItem
end repeat
...
Use a Finder tell block only if you are going to use Finder terminology.
The mentioned Droplet is your app.
Objective: Move all files and files in folders to destination folder and maintain the file structure [files and named folders]. Important for music files in albums.
Functional: Move all listed files in SmartFolder [named] to destinationFolder with serial / consecutive move operation and maintain the same file structure and copy of dataFiles listed in SmartFolder.
Key: All files were obtained for transfer. Normal CMD + A, CMD + C, CMD + V hangs up the computer and the transfer does not initiate. The AppleScript to move each dataObject to destinationPath is all.
Facts: How to reference objects [files, folders] and their proper reference format and accepted path syntax; path or POSIX, and use of alias. Basic operations. I ran an AppleScript to move filePath to pathDestination, and was otherwise successful, and would be nice to known the formalization syntax for path reference.
tell application "Finder"
move allFiles to destinationFolder
// recursive/repeat code to loop through all listed files and folder
end tell
Reference: Applescript, show all files with tag
[Moving / selecting listed files from 'smartfolder' containers as active windows and displayLists. It was an alt. solution since AppleScript will not reference the SmartFolder as an object, nor will it dynamically call the listProperty of the SmartFolder object unless called by an unknown or un-reference method or command.
Since your main issue, as far as I can tell, seems to be dealing with SmartFolders in AppleScript, which—as you said—cannot be referenced as folder objects, this little snippet might be of help:
set SmartFolder to "/Users/CK/My Smart Folder.savedSearch"
tell application "System Events" to get value of property list file SmartFolder
set {[Scope], Query} to {SearchScopes, RawQuery} of RawQueryDict of result
set AppleScript's text item delimiters to tab
set Command to {"mdfind -onlyin", ¬
quoted form of Scope as text, ¬
quoted form of Query as text} as text
set SearchResults to paragraphs of (do shell script Command)
--> returns a list of posix files
--> e.g. {"/Users/CK/Downloads/This is file one.txt", ...}
This will return a list of POSIX paths to files that match the search criteria.
I would recommend using System Events rather than Finder to deal with large numbers of files. It can also handle posix paths without the need to manually coerce them into aliases or whatever. So, given a posix path, such as the ones returned in the list using the above code snippet, you simply do this:
set myfile to item 1 of SearchResults
tell application "System Events" to move myfile to "/Users/CK/Desktop"
Without knowing more details of what your smart folder contains (since some searches could easily return a folder plus the contents of that folder, which you'd have to bear in mind when getting your AppleScript to recurse through the search results), I can't give you more than that. But, you said your main problems were being unable to handle SmartFolders and not knowing how to reference files/folders.
This works for me using the latest version of Sierra.
Set the value of property moveToNewFolderto the destination folder of your choice
This script creates a "Choose From List" Dialog, allowing you to choose any smart folder which resides on your system. It will then move all of these files and folders in the chosen smart folder, to your set destination folder.
property savedSearches : (path to home folder as string) & "Library" & ":Saved Searches"
property savedSearchesSubFolders : {}
property namesOfSavedSearchesSubFolders : {}
property selectedSearchFolder : ""
property selectedSearchFolderPath : missing value
property moveTheseItems : missing value
property moveToNewFolder : (path to desktop as text) & "untitled folder" -- change this value to your preferred destination folder
tell application "Finder"
activate
delay 0.1 -- may need to adjust delay time value
open savedSearches
delay 0.1 -- may need to adjust delay time value
reveal savedSearches
delay 0.1 -- may need to adjust delay time value
select savedSearches
delay 0.1 -- may need to adjust delay time value
set current view of Finder window 1 to column view
delay 0.1 -- may need to adjust delay time value
tell its Finder window (POSIX path of savedSearches)
delay 0.1 -- may need to adjust delay time value
set savedSearchesSubFolders to items
set namesOfSavedSearchesSubFolders to name of items
-- Allows to choose any smart folder from a list of all smart folders
set selectedSearchFolder to choose from list namesOfSavedSearchesSubFolders ¬
with title ¬
"Smart Search Folders" with prompt ¬
"Choose Your Folder" OK button name ¬
"OK" cancel button name "CANCEL"
set selectedSearchFolder to selectedSearchFolder as text
set selectedSearchFolderPath to savedSearches & ":" & selectedSearchFolder
set selectedSearchFolderPath to selectedSearchFolderPath as string
end tell
delay 0.2 -- may need to adjust delay time value
select selectedSearchFolderPath
tell Finder window 1
set defaultView to current view
set current view to list view
delay 0.1 -- may need to adjust delay time value
set current view to defaultView
delay 0.5 -- may need to adjust delay time value
tell application "System Events"
key code 0 using command down
end tell
end tell
set moveTheseItems to selection
end tell
tell application "Finder"
set resultObject to move moveTheseItems ¬
to moveToNewFolder ¬
with replacing
end tell
I am trying to move a file with AppleScript. This Is the code I use:
on adding folder items to this_folder after receiving these_items
repeat with i from 1 to number of items in these_items
set this_item to item i of these_items
set the item_info to info for this_item
set the item_path to the quoted form of the POSIX path of this_item
...
... //irrelevant code here
...
tell application "Finder"
move POSIX file item_path to POSIX file "/Users/mainuser/Desktop/Books"
end tell
end repeat
end adding folder items to
If I replace item_path with a regular path such as /Users/mainuser/Desktop/Test/test.png than it works great. What could be the reason for my problem?
these_items is an array of alias specifiers, any further coercion is not needed
tell application "Finder"
move this_item to folder "Books" of desktop
end tell
the property desktop points always to the desktop of the current user.
By the way: The Finder doesn't accept POSIX paths (slash separated), only the native HFS paths (colon separated).
PS: The reason why item_path does not work is the quotation.
It's only needed in do shell script
Use:
on adding folder items to this_folder after receiving these_items
tell application "Finder" to move these_items to folder "Books" of desktop
end adding folder items to
The after receiving parameter is a list of AppleScript alias values, which is something Finder's move command already understands and knows how to work with. While it's unusual for application commands like move to accept values that aren't references to application objects, it's not completely unknown; particularly with pre-OS X apps like Finder whose scripting support was completely hand-written, allowing developers to make it work in ways that would be helpful to users and not just in ways dictated by dumb, standardized frameworks like OS X's Cocoa Scripting.
I'm new to applescript but I want to set up a folder action that:
1. Recognises when a file is added to a folder
2. Tags said folder red
3. Adds a Reminder to the "Downloads" reminder list that has the name of the newly-added file as the body text of the reminder
Using google and Applescript's record function I've frankenscripted this together so far
property dialog_timeout : 30 -- set the amount of time before dialogs auto-answer.
on adding folder items to this_folder after receiving added_items
try
tell application "Finder"
set FILEname to name of (added_items)
set label index of folder "untitled folder" of folder "Desktop" of folder "heyjeremyoates" of folder "Users" of startup disk to 2
end tell
tell application "Reminders"
set mylist to list "Downloads"
tell mylist
make new reminder with properties {name:"D/L Complete", body:FILEname, due date:(current date)}
end tell
end tell
end try
end adding folder items to
Darn thing won't work. Infuriating. I tested it as a folder action with "test" as the name and body of the reminder and it worked fine. I'm pretty sure I've gone wrong somewhere in setting FILEname as the name of the newly copied item because the script as it is now no longer turns the folder red.
The idea behind this is so I can see, from my iPhone/iPad, how many large/scheduled downloads to my home mac (both torrents and large work files - I'll have a seperate folder action and reminder list for each download folder) there are that are yet to be managed.
It seemed like setting up a Growl/Prowl combo was wasteful if iCloud/Reminders and a dozen lines of code could deliver what I wanted anyway. Ideally I'll write a second applescript that will delete the reminder when I rename or move the related file, and though I haven't even thought about how that would work if anyone has any suggestions for it I'd be super grateful
It is a pity you can't (natively) have OSX notifications pushed to an iOS device linked to the same iCloud account though (with the appropriate granularity)
But I digress - can anyone see what I'm screwing up here?
Thanks in advance for even reading this far
added_items is a list of aliases, and name of (added_items) resulted in an error.
on adding folder items to this_folder after receiving added_items
tell application "Finder"
set label index of this_folder to 2
repeat with f in added_items
set n to name of f
tell application "Reminders" to tell list "Downloads"
make new reminder with properties {name:"D/L Complete", body:n, due date:(current date)}
end tell
end repeat
end tell
end adding folder items to
(Save the script in ~/Library/Workflows/Applications/Folder Actions/ and enable the folder action from Folder Actions Setup.)