I have a list of jpeg images on a local server that I use an AppleScript droplet to resize in Photoshop. I use "on open" to do this, but something strange happens: they open in two parts.
The files are named as follows:
0_203.jpg
1_203.jpg
2_203.jpg
3_203.jpg
4_203.jpg
5_203.jpg
6_203.jpg
7_203.jpg
8_203.jpg
9_203.jpg
10_203.jpg
11_203.jpg
12_203.jpg
13_203.jpg
14_203.jpg
15_203.jpg
16_203.jpg
17_203.jpg
18_203.jpg
19_203.jpg
20_203.jpg
The script should do its actions to each file in turn, but something strange happens: it breaks the files into two groups and runs the script twice. The script splits the groups like this:
1_203.jpg
2_203.jpg
3_203.jpg
4_203.jpg
5_203.jpg
6_203.jpg
7_203.jpg
8_203.jpg
9_203.jpg
10_203.jpg
11_203.jpg
12_203.jpg
...and then runs again with these files...
0_203.jpg
13_203.jpg
14_203.jpg
15_203.jpg
16_203.jpg
17_203.jpg
18_203.jpg
19_203.jpg
20_203.jpg
What the hell is going on here?
Here's the test script I used to debug:
on open myItems
set myList to {}
set AppleScript's text item delimiters to ":"
repeat with thisItem in myItems
set newItem to thisItem as string
copy newItem to end of myList
end repeat
display dialog myList as string
end open
See the question and answers posted here. I gave a work-around as a solution.
Related
Purely as an experiment, I’m trying to do something rather complex with AppleScript, mostly as an academic exercise more than anything, but I’m running into trouble. Here’s what’s happening.
First, I have a code library, called “ascr_code_library.scpt”, containing just one method:
on return_string_position(this_item, this_str, delim)
set old_delims to AppleScript's text item delimiters
set AppleScript's text item delimiters to delim
set this_list to text items of this_str
set found_pos to 0
repeat with i from 1 to the count of this_list
if item i of this_list is equal to this_item then set found_pos to i
end repeat
set AppleScript's text item delimiters to old_delims
return found_pos
end return_string_position
Then, I have this script, “test-2.scpt.” What it does is very simple, and pretty self-explanatory:
set scr_lib to load script (choose file with prompt "Please pick a library")
tell scr_lib
return_string_position("Who", "Who am I?", " ")
end tell
But what I get when I run the script and choose the file is the following error:
*“«data scpt4D617259332E303000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 . . . . . . . (etcetera, goes on fou five pages) . . . 1000101010CFADEDEAD» doesn’t understand the return_string_position message.”*
So where am I going wrong? It’s loading the script correctly, so far as I can tell. But where else could I be going wrong in such a simple script? I tried prefixing the method call with “my,” but that didn’t work either. Any ideas?
As mentioned in your previous question, I like this script better because it avoids delimiters and returns each instance.
on return_string_position(this_item, this_str)
set theWords to every word of this_str
set matchedWords to {}
repeat with i from 1 to count of theWords
set aWord to item i of theWords
if item i of theWords = this_item then set end of matchedWords to i
end repeat
return matchedWords
end return_string_position
return_string_position("very", "The coffee was very very very very very ... very hot.")
You can call the script like this:
run script file ((path to desktop as text) & "test 1.scpt") with parameters {"very", "The coffee was very very very very very ... very hot."}
I have some AppleScript code that I'm executing with osascript. This is part of a larger Perl program. I'd like to be able to print to stdout from the AppleScript, then have the Perl script process the output. But I haven't been able to print from within AppleScript. What should I do?
Here's what I've tried:
do shell script "echo Foo". Does not ouptut Foo.
This Google Groups discussion does some trickery to open /dev/fd/1. For me, I get an error of "File Macintosh HD:dev:fd:1 wasn't found"
Here's the script I'm running:
tell application "Safari"
set window_list to every window
repeat with the_window in window_list
set tab_list to every tab in the_window
repeat with the_tab in tab_list
set the_url to the URL of the_tab
-- I'd like to put a print statement here,
-- instead of display dialog
display dialog the_url
end repeat
end repeat
end tell
Since osascript will automatically print the last value of a program, I could collect the URLs into a list and print that. But then my Perl script would have to parse the list, remove quotes, etc. It seems like it should be more straightforward to just print one URL per line.
Thanks
I don't know how to do what you're asking and I don't know Perl, however I think you could make the parsing from perl simple if you collect your urls in a string instead of a list. Each url would be on a separate line of the string. Perl should be able to turn that into an array pretty easily and then do something with it. Something like the below applescript. Of course you can use a different separator in the applescript. I used "return" but it could just as easily be a "comma" or any other character you want. Whatever is easiest for you in perl to change the string to an array.
set urlString to ""
tell application "Safari"
set window_list to every window
repeat with the_window in window_list
set tab_list to every tab in the_window
repeat with the_tab in tab_list
set the_url to the URL of the_tab
set urlString to urlString & the_url & return
end repeat
end repeat
end tell
return text 1 thru -2 of urlString
I found that I can use 'log' to dump results to STDERR,
though I had to use Chrome instead of Safari:
#!/usr/bin/osascript
tell application "Chrome"
repeat with w in every window
repeat with t in tabs of w
log (get URL of t)
end repeat
end repeat
end tell
Just use log is OK.
MacBookPro:~ zxj5470$ cat demo.scpt
tell application "Terminal"
set WindowNum to get window count
log WindowNum
end tell
MacBookPro:~ zxj5470$ osascript demo.scpt
1
I have one or many files and/or folders selected in the Finder. I manually copy them to the clipboard/pasteboard (⌘C).
To keep things simple, let's say I just copied one single normal file. The ideal solution, however, would deal with many files and a mixed selection with folders, aliases.
Now that this file is on the clipboard, I want to get its full path (preferably the POSIX path).
To save you time:
I'm looking for an AppleScript (or rb-appscript) solution.
I don't want to get the path directly from the selection. It must be from the item on the clipboard.
Really, I know I can route around this by copying the path(s) to the selection first, then doing whatever I'm up to with it.
What I know so far (noted in rb-appscript):
OSAX.osax.the_clipboard has a string of file names without path.
Appscript.app('Finder').clipboard.get is apparently not implemented (dictionary says "NOT AVAILABLE YET"; calling it returns :missing_value.
The following AppleScript seems to do the trick:
POSIX path of (the clipboard as «class furl»)
If there are multiple items on the clipboard, it will return the POSIX path of the first item only.
Also see the AppleScript command reference for the command the clipboard.
rb-appscript version:
OSAX.osax.the_clipboard(:result_type => :file_url).path
Here's an applescript that will get all of the posix paths from the clipboard, not just the first one...
set theFiles to paragraphs of (get the clipboard)
set posixPaths to {}
repeat with aFile in theFiles
try
tell application "Finder" to set thePath to item aFile as text
set end of posixPaths to (POSIX path of thePath)
end try
end repeat
return posixPaths
The Finder being what it is, and AppleScript being what it is, it's all too much fail to go around. So, what the hell, I jumped into Cocoa.
Either of these scripts will return the list of absolute paths each on a new line.
MacRuby:
#!/usr/bin/env macruby
# encoding: UTF-8
framework 'Cocoa'
puts NSPasteboard.generalPasteboard.pasteboardItems
.map { |pbi| pbi.stringForType('public.file-url') }.compact
.map { |url| NSURL.URLWithString(url).path }
Nu:
#!/usr/bin/env nush
(puts ((((((NSPasteboard generalPasteboard) pasteboardItems)
map: (do (pbi) (pbi stringForType: "public.file-url")))
select: (do (url) (url)))
map: (do (url) ((NSURL URLWithString: url) path))) componentsJoinedByString: "\n"))
just thought I'd share the rb-appscript code that I wrote after sakra's answer:
#!/usr/bin/arch -i386 /usr/bin/ruby
require "rubygems"
require "osax"
include OSAX
def path_from_clipboard
osax.clipboard_info.flatten.include? :file_url or raise "clipboard does not contain path data"
osax.the_clipboard.count("\r") == 0 or raise "clipboard contains more than one path"
osax.the_clipboard(:result_type => :file_url).path
end
puts path_from_clipboard
I was looking for a solution that would copy the path of the files selected in the Finder. Here is what I came up with :
set ASTID to AppleScript's text item delimiters --——>>
set AppleScript's text item delimiters to return
tell application "Finder" to set sel to the selection as text
set listPaths to {}
repeat with pth in paragraphs of sel
set end of listPaths to POSIX path of pth
end repeat
set listPathsClipboard to listPaths as text
set AppleScript's text item delimiters to ASTID --——<<
set the clipboard to listPathsClipboard
I have a shell script that outputs filenames (one per line). I want to put that output into a list in AppleScript.
How can I do this?
Bonus points for how to then turn those filename strings into file objects.
EDIT:
When trying this:
set theFiles to {}
repeat with i from 1 to count of filenames
set end of theFiles to (POSIX file (item i of filenames))
end repeat
I get this:
error "Finder got an error: Can’t get POSIX file \"/path/to/file\"." number -1728 from file "Macintosh HD:path:to:file"
EDIT-2:
Turns out finder isn't aware of a file that gets created after the "tell" statement starts. How do I update it or make it aware of the new file?
EDIT-3:
This worked (note the addition of "my"):
set theFiles to {}
repeat with i from 1 to count of filenames
set end of theFiles to (my POSIX file (item i of filenames))
end repeat
set myFilenamesList to paragraphs of (do shell script "path/to/shell/script")
set firstFileObject to POSIX File (item 1 of myFilenamesList)
When you have a list, you use a repeat loop to iterate over the list and do something with the items in the list. For example if you wanted a list of the file objects you could do this.
set fileObjectsList to {}
repeat with i from 1 to count of myFilenamesList
set end of fileObjectsList to POSIX File (item i of myFilenamesList)
end
return fileObjectsList
Of course it doesn't make much sense to do this because once you have the file objects in a list then you'll need to repeat over that list to do something with those objects... thus you'll be repeating over a list 2 times when 1 time would probably suffice. So I would do something like this instead...
repeat with i from 1 to count of myFilenamesList
set thisFileObject to POSIX File (item i of myFilenamesList)
-- do something with the file object "thisFileObject"
end
I made this Applescript script to create symbolic links.
Appart from POSIX path of, how can I get the file name, without the path, of the dropped file?
on open filelist
repeat with i in filelist
do shell script "ln -s " & POSIX path of i & " /Users/me/Desktop/symlink"
end repeat
end open
PS: I know this expects many files to be dropped and tries to create many links with the same name, which gives an error. Actually I copied this example from a website and as I don't know almost anything about Applescript, I don't know how to do this for a single file, help on that would be appreciated too.
I'm not sure what precisely you're trying to do, but I have a guess. Is the idea that you want to take every file dropped on the script and create a symbolic link to each one on the Desktop? So if I drop ~/look/at/me and ~/an/example, you'll have ~/Desktop/me and ~/Desktop/example? If that's what you want, then you're in luck: ln -s <file1> <file2> ... <directory> does exactly that. (Edit: Although you have to watch out for the two-argument case.) Thus, your code could look like this:
-- EDITED: Added the conditional setting of `dest` to prevent errors in the
-- two-arguments-to-ln case (see my comment).
on quoted(f)
return quoted form of POSIX path of f
end quoted
on open filelist
if filelist is {} then return
set dest to missing value
if (count of filelist) is 1 then
tell application "System Events" to set n to the name of item 1 of filelist
set dest to (path to desktop as string) & n
else
set dest to path to desktop
end if
set cmd to "ln -s"
repeat with f in filelist & dest
set cmd to cmd & " " & quoted(f)
end repeat
do shell script cmd
end open
Note the use of quoted form of; it wraps its argument in single quotes so executing in in the shell won't do anything funny.
If you want to get at the name of the file for another reason, you don't need to call out to the Finder; you can use System Events instead:
tell application "System Events" to get name of myAlias
will return the name of the file stored in myAlias.
Edit: If you want to do something to a single file, it's pretty easy. Instead of using repeat to iterate over every file, just perform the same action on the first file, accessed by item 1 of theList. So in this case, you might want something like this:
-- EDITED: Fixed the "linking a directory" case (see my comment).
on quoted(f)
return quoted form of POSIX path of f
end quoted
on open filelist
if filelist is {} then return
set f to item 1 of filelist
tell application "System Events" to set n to the name of f
do shell script "ln -s " & ¬
quoted(f) & " " & quoted((path to desktop as string) & n)
end open
It's pretty much the same, but we grab the first item in filelist and ignore the rest. Additionally, at the end, we display a dialog containing the name of the symlink, so the user knows what just happened.
As an example, you can work with the Finder instead of a shell script to get the name of a single file that is dropped on the script that is saved as an application. If you don't need the display dialog, you can remove it, but you have the file name as a variable to work with:
on open the_files
repeat with i from 1 to the count of the_files
tell application "Finder"
set myFileName to name of (item i of the_files)
end tell
display dialog "The file's name is " & myFileName
end repeat
end open