Print to stdout from osascript/Applescript - applescript

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

Related

Remove specific characters from highlighted text using AppleScript or Automator

I have a question and maybe someone can point me in the right direction.
I would like to be able to copy Text (mostly from "Get Info") and replace all the “.” with a space excluding the “.”before the file extension using AppleScript or Automator. I'd like to use this service when i right click and select the script or automator service.
E.G
Contraband.2012.DVDRip.htif-NYsIC.avi
will turn to
Contraband 2012 DVDRip htif-NYsIC.avi
I've search everywhere on this site and various places but I just cant seem to find what i need. I don’t know where to start writing this script. Is what i described even possible in apple script? I just need to be pointed in the right direction and I'll try and figure the rest out I'm just at a loss right now.
Thank's in advance.
You could use a Run Shell Script action like this:
for f; do
base=${f##*/}
[[ $base =~ .+\..+ ]] || continue
noext=${base%.*}
mv "$f" "${f%/*}/${noext//./ }.${base##*.}"
done
Set "Pass input" to "as arguments". ${f##*/} removes the longest */ pattern from the start of f and ${f%/*} removes the shortest /* pattern from the end of f.
You could also use a Run AppleScript action like this:
on run {input}
repeat with f in input
set text item delimiters to "."
tell application "Finder"
set ti to text items of (get name of (f as alias))
if number of ti > 2 then
set AppleScript's text item delimiters to " "
set name of (f as alias) to (items 1 thru -2 of ti as text) & "." & item -1 of ti
end if
end tell
end repeat
end run

OSX: How can check whether a file exists in current directory using applescript?

I want to make an automator app which creates an empty file in current directory.
I did some google search and found:
http://hints.macworld.com/article.php?story=20050219134457298 and http://hints.macworld.com/article.php?story=20100509134904820
However, I want to do something more powerful.
If the specified file already exists, I want to show a warning instead of overwriting the original file, which is what one of the above link does. (The other one creates a text file using textEdit. I do not want to create text file. I want an empty file like what linux/unix does)
I already figured out how to do most of the part, but
How can check whether a file exists in current directory using applescript??
How can I concatenate two variable in applescript?
Checking if a file exists (assuming thefullpath is already set as in the referenced question):
tell application "Finder"
if exists POSIX file thefullpath then
--do something here like
display alert "Warning: the file already exists"
end if
end tell
Not sure what you mean by the second part but if you want to concatenate strings stored in var1 and var2 you could simply do
var1 & var2
Something I have been using a lot of late for this sort of thing is the command /bin/test
The test test for the existence of in this case a file
if (do shell script "/bin/test -e " & quoted form of (POSIX path of theFile) & " ; echo $?") is "1" then
-- 1 is false
--do something
end if
The -e option:
-e file True if file exists (regardless of type).
The are tons of other test options shown in the /bin/test man page
The following code, adapted from your second link, is usually right, but it doesn't always work. The current directory is better specified as the directory of the document that is being opened which is most likely from the Finder's front window, but not necessarily. I like to write code that will work no matter what.
on run {input, parameters}
tell application "Finder"
set currentPath to insertion location as text
set x to POSIX path of currentPath
display dialog "currentPath: " & (x as text)
end tell
return x
end run
I wrote a whole "Run AppleScript" action to put things into context:
on run {input, parameters}
# count the number of files
set numFiles to 0
repeat with f in input
# warn the user that folders are not processed in this app
tell application "Finder"
if (kind of f is "Folder") then
display dialog "The item: " & (f as text) & " is a folder. Only files are allowed. Do you want to continue processing files or do you want to cancel?"
else
set numFiles to numFiles + 1
end if
end tell
end repeat
# require that at least one file is being opened
if numFiles < 1 then
display alert "Error: the application Test1.app cannot be run because it requires at least one file as input"
error number -128
end if
# get the current directory from the first file
set theFirstFile to (item 1 of input)
tell application "System Events" to set theFolder to (container of theFirstFile)
# ask the user for a file name
set thefilename to text returned of (display dialog "Create file named:" default answer "filename")
# create the file
tell application "System Events" to set thefullpath to (POSIX path of theFolder) & "/" & thefilename
set theCommand to "touch \"" & thefullpath & "\""
do shell script theCommand
# return the input as the output
return input
end run
The "touch" command is OK. If the file doesn't exist, it is created and if it does exist, only the modification date is changed (which isn't too bad) but it doesn't overwrite the file. If your file is being overwritten, it's not the touch command that is doing it.
I changed the default file name to remove the extension ".txt" This extension may default to being opened by TextEdit.app, but you can change this in the Finder by choosing "Get Info" for a file and changing the "Open With" property. You can change which application opens the file with that extension or you can change them all. For example, all of my ".txt" files are opened with BBEdit.app
Will you vote my answer up?
Another option that doesn't require Finder or System Events is to try to coerce a POSIX file or file object to an alias:
try
POSIX file "/tmp/test" as alias
true
on error
false
end try

How to copy every line of text on a text file with Automator on OSX?

The deal is this:
I use http://www.clipmenu.com/ ClipMenu to have 20 states of the clipboard, because i need to copy each line of some txt file separated. So i open the txt file, and i go through every line hitting command+shift+→ then command+c then ↑ and so on until i reach the top and i have all the lines copied and stored in the history of ClipMenu.
My question is, is there a way to make a service or script that copies every single line in an automated way? i think i could make a script that repeat those keystrokes until it reaches the top of the txt file but i have no idea how to make it so.
Thanks a lot.
I do not know how to do this using Automator, but using mono [MonoMac] it is very simple:
using (System.IO.FileStream file = new System.IO.FileStream("path", System.IO.FileMode.Open, System.IO.FileAccess.Read, System.IO.FileShare.Read)) {
using (System.IO.StreamReader reader = new System.IO.StreamReader(file)) {
while (!reader.EndOfStream) {
String line = reader.ReadLine ();
System.Windows.Forms.Clipboard.SetText(line);
}
}
}
Try:
set fileText to read (choose file) as «class utf8»
set filePara to paragraphs of fileText
repeat with aPara in filePara
set aPara to contents of aPara
if aPara ≠ "" then set the clipboard to aPara
end repeat
ClipMenu seems to ignore "transient" clipboards, so you also need a delay between the copy actions:
read POSIX file "/Users/username/Documents/test.txt" as «class utf8»
repeat with p in reverse of paragraphs of result
if contents of p is not "" then set the clipboard to contents of p
delay 1
end repeat
Or using UI scripting:
delay 1
tell application "TextEdit"
activate
set n to number of paragraphs of document 1
end tell
tell application "System Events"
key code {125, 123} using command down
repeat n times
key code 124 using {shift down, command down}
keystroke "c" using command down
key code 126
delay 1
end repeat
end tell
The key codes are listed in Events.h.

AppleScript and loading code libraries

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."}

Getting the file name of files dropped on the script

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

Resources