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.
Related
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.
I created a droplet which would allow me to rename files from an input box.
on adding folder items to este_folder after receiving este_file
display dialog "what's their name?" default answer ""
set text_returned to text returned of the result & ".jpg"
display dialog text_returned
tell application "Finder"
set the name of file este_file to text_returned
end tell
end adding folder items to
It works fine, but it creates a loop where I have to hit cancel again to stop the script, as it thinks a new file has been added. I would like to just rename it once; and then not have the second dialog box pop up again. I have tried rerouting the file to another folder:
on adding folder items to este_folder after receiving este_file
display dialog "what's their name?" default answer ""
set text_returned to text returned of the result & ".jpg"
display dialog text_returned
tell application "Finder"
set the name of file este_file to text_returned
end tell
repeat with anItem in este_file
tell application "Finder"
set destFolder to "Macintosh HD:Users:maxwellanderson:Desktop:BetterinTexas" as alias
move anItem to folder destFolder
end tell
end repeat
end adding folder items to
But that doesn't work either-it doesn't process the renaming portion of the script. Any suggestions on what I should do to get rid of the second dialog box?
The script is being called twice because renaming the file within the watched folder is—for all intents and purposes—like adding a new file into the folder. Therefore, it's called once when the file is actually added; and called a second time when it's renamed.
Moving the file as you suggested will work, but you have to move the file before you rename it. Therefore, shove the code that moves the file near the top of the script, then the renaming bits at the bottom.
As a side-note, I notice you have a repeat with loop to handle multiple file moves, but only one statement that handles a single file renaming. One of these is not like the other. If this watched folder received multiple files at the same time, it would most likely rename them all to the same name, thus potentially over-writing multiple files. If the watched folder only ever receives one file at a time, anyway, then the repeat with loop is redundant.
This code is modelled on yours and will handle a single file move-and-rename (but not a group of files—or, more accurately, as I stated above, it would rename multiple files to the same name, thus overwriting all but the last one in the list):
on adding folder items to este_folder after receiving este_file
set destFolder to POSIX file "/Users/maxwellanderson/Desktop/BetterinTexas" as alias
set text_returned to text returned of ¬
(display dialog "what's their name?" default answer "") ¬
& ".jpg"
display dialog text_returned
tell application "Finder" to ¬
set the name of ¬
(move file este_file to destFolder) ¬
to text_returned
end adding folder items to
If you need it to handle multiple files, then you can wrap everything from set text_returned to to text_returned in a repeat with loop as you've done in your second code block. This will sequentially bring up dialog boxes—one per file—and move/rename the files accordingly.
If you have any questions, or need clarification, leave a comment and I'll get back to you.
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 trying to automate JPEGmini which is not entirely scriptable - the only way to control it is via the "Open" dialog.
Repeatedly calling it once per image is extremely slow.
Instead I'm trying to to perform a search for .jpg or .jpeg files in the "Open" dialog, so that within that result set I can select the batch of files I want to process and open them in a single pass.
(More detail after the code example)
-- later within the search results list I get, I want to select these
set filesToSelect to {"/Users/me/Desktop/photo.jpg", "/Users/me/Documents/image.jpeg"}
-- the actual app is JPEGmini but the same principle applies to Preview
tell application "Preview"
-- start the app
activate
-- let it boot up
delay 3
-- ensure it still has focus
activate
end tell
tell application "System Events"
tell process "Preview"
-- spawn "Open" window
keystroke "o" using {command down}
delay 1
-- spawn "Go to" window
keystroke "g" using {command down, shift down}
delay 1
-- Go to root of hard drive
keystroke "/"
keystroke return
delay 1
-- Perform search
keystroke "f" using {command down}
delay 1
keystroke ".jpg OR .jpeg"
keystroke return
end tell
end tell
Having done the above, how do I access the list of search results, repeat over each item and get it's absolute file path?
I've tried a few variations but am getting nowhere.
Thanks for your time.
You could simplify this by using cross between the shell command line and applescript.
set jpegSearch to paragraphs of (do shell script "mdfind -onlyin / 'kMDItemContentType == \"public.jpeg\" '")
The mdfind command
consults the central metadata store and returns a list
of files that match the given metadata query. The query can be a string
or a query expression.
AFAIK this is what spotlight uses.
mdfind documents will give you an idea of how this command works. But ths script searches only in "/" and looks for content type attribute that is public.jpeg
The return is text. A list of POSIX Paths of the matching files. This text is like a text document each path on a new line but in effect one item as far as Applescript is concerned.
They need to be broken up in a applescript list. So I do this by asking for the paragraphs of the result.
Also if you want to open a new finder window:
try something like:
tell application "Finder"
activate
set myWindow to make new Finder window to startup disk
end tell
To answer why you are getting your error in trying to get the POSIX paths of the target of the files.
If you look at the properties of one of the files returned in your Search Window.
tell application "Finder" to set fileList to properties of first file of front window
You will see the file properties have a property named original item
If you really want to do it the way you are doing it then one way is to get the original item. Coerce the result into alias form then get the posix path.
tell application "Finder" to set aFile to POSIX path of (original item of first file of front window as alias)
In a normal finder window you can use.
tell application "Finder" to set fileList to POSIX path of (first file of front window as alias)
These are just examples to show you whats going on.
The difference in the type of finder window results is because in a Search window what is being displayed is alias files (class:alias file) to the original files, hence the original item property.
Update 2.
To go through your items in your list and check them against another list is simple.
Apple have some tools that will help you with the code.
When in your script.
crtl + Mouse Click the Variable that will hold the jpg result as a list.
This will give you a contextual menu that contains helper code.
Go to the Repeat routines folder in the menu.
Then to its 'Process Every Item'
This will add a repeat routine to your code.
And from there you can use it to check each item against your other list.
set yourOtherList to {"/Library/Desktop Pictures/Abstract/Abstract 2.jpg", "/Library/Desktop Pictures/Abstract/Abstract 1.jpg"}
set jpegSearch to paragraphs of (do shell script "mdfind -onlyin / 'kMDItemContentType == \"public.jpeg\" '")
repeat with i from 1 to number of items in jpegSearch
set this_item to item i of jpegSearch
if this_item is in yourOtherList then
-- do something
log this_item
end if
end repeat
The repeat routine works like this.
It loops over each item in the given list
It will iterate from item 1 to the count of the items in the list.
The i variable holds the loop iteration number. I.e it will be 1 on the first loop and 300 on the 300th loop.
so on the first loop set this_item to item i of jpegSearch is equivalent to writing set this_item to item 1 of jpegSearch
But apple saves you having to write each number of each item with the Repeat with i..
The variable i can be any word or letter you choose that conforms to the normal allowed Variable naming syntax.
Something you can do is build a new list from the matched items. by copying them into a previously declared list. You can then work on that list after the repeat loop has completed.
Here bigList is declared as a empty list {}
The matched items are copied to the bigList. Each new item it receives is added to the end of the list.
set bigList to {}
set yourOtherList to {"/Library/Desktop Pictures/Abstract/Abstract 2.jpg", "/Library/Desktop Pictures/Abstract/Abstract 1.jpg"}
set jpegSearch to paragraphs of (do shell script "mdfind -onlyin / 'kMDItemContentType == \"public.jpeg\" '")
repeat with i from 1 to number of items in jpegSearch
set this_item to item i of jpegSearch
if this_item is in yourOtherList then
copy this_item to end of bigList
end if
end repeat
bigList
I need to open multiple Safari (or open the tab is OK) based on the read result.
For example, if a file has
http://a.com
http://b.com
I want to open a.com and b.com using Safari.
How can I do that with Mac/AppleScript?
Maybe I can run python calling "open -a Safari "http://a.com", but I guess AppleScript is the tool for this kind of job.
not sure about python but this will read a text file and open windows let me see if I can get tabs for you though
set locations to paragraphs of (read (choose file with prompt "Pick text file containing urls"))
repeat with aline in locations
if length of aline is greater than 0 then
tell application "Safari"
make new document at end of documents
set URL of document 1 to aline
end tell
end if
end repeat
EDIT:
Ok this is better and it opens them in tabs of a single window
set locations to paragraphs of (read (choose file with prompt "Pick text file containing urls"))
tell application "Safari"
activate
set adoc to make new document
end tell
repeat with aline in locations
if length of aline is greater than 0 then
tell application "Safari" to make new tab at end of window 1 with properties {URL:aline}
end if
end repeat
New Addtion
this is yet another way based on regulus6633's post in conjunction with mine
set locations to paragraphs of (read (choose file with prompt "Pick text file containing urls"))
repeat with aLocation in locations
tell application "Safari" to open location aLocation
end repeat
If you want it to specifically open the links in Safari then mcgrailm's solution is good. However, you don't need the Finder for the first part so take that code out of the Finder tell block. There's no need to tell the Finder to do something that applescript can do itself.
However, you probably want to open the links in whatever browser is the user's default browser. It may be Safari or Firefox etc. You can do that with the "open location" command. So something like this is probably what you want...
set theFile to choose file with prompt "Pick text file containing urls"
set locations to paragraphs of (read theFile)
repeat with aLocation in locations
try
open location aLocation
end try
end repeat