Multiple Applescript lines from terminal osascript call - applescript

So I'm trying to run multiple Applescript commands from the command line in one go. However, no matter how I try it, it won't work:
$ osascript -e "set x to 0; display dialog x"
$ osascript -e "set x to 0 \n display dialog x"
$ osascript -e "set x to 0 then display dialog x"
Is there a way to do this without saving to file?

This works for me:
osascript -e "set x to 0" -e "display dialog x"
Have a look at the -e option in the manual page for osascript in Terminal: man osascript
−e statement
Enter one line of a script. If −e is given, osascript will not look for a filename in the argument list. Multiple −e options may be given to build up a multi-line script. Because most scripts use char- acters that are special to many shell programs (for example, AppleScript uses single and double quote marks, “(”, “)”, and “∗”), the statement will have to be correctly quoted and escaped to get it past the shell intact.
You can also do e.g.:
osascript <<END
set x to 0
display dialog x
END
Or:
osascript -e '
set x to 0
display dialog x'

Your second attempt was very close to proper:
osascript -e "set x to 0
PRESS ENTER
display dialog x"
PRESS ENTER

Related

osascript 'do shell script' line endings

I'm trying to debug an larger osascript 'do shell script' program and have narrowed the problem down to a much shorter repro case that I don't understand at all. Here's the repro case:
osascript -e 'do shell script "echo 123; echo 45; echo 6"'
Gives me the output:
653
Can anybody explain what's going on? It's almost like 'do shell script' does not properly handle line endings, or tries to print everything on one line.
Applescript replaces \n characters with \r characters when reading the output of a shell script. You can tell this is happening by running the output through od -c:
$ osascript -e 'do shell script "echo 123; echo 45; echo 6"' | od -c
0000000 1 2 3 \r 4 5 \r 6 \n
0000011
To turn this off, use the without altering line endings parameter.
osascript -e 'do shell script "echo 123; echo 45; echo 6" without altering line endings'
See Technical Note TN2065 for more.

How to programatically paste to terminal without executing?

Is it possible to type / paste something to the console without executing the command? Something that would emulate the normal Ctrl / Cmd + c, Ctrl / Cmd + v where the text is put on the current line without being executed so the user can continue typing, deleting, etc.
For example I have the following simple script:
#!/bin/bash
echo -n "foo" | pbcopy
pbpaste
Now when I run this, it just echoes foo% and goes on the next line.
Also, even if this would work, I would prefer a solution that works on both mac os and ubuntu (as far as I know pbcopy does not come pre-installed on all linux distros).
EDIT
Edit to explain the scenario better. Imagine the script above is called foo.sh. You run the script ./foo.sh and when it finishes you have a new prompt with only the text "foo"|. The | represents the cursor.
So... You already know about pbcopy and pbpaste in macOS. You probably want to know about xclip, which is a similar interface to X selections ("the clipboard") from the command line.
Each system (Aqua and X) handles clipboard data structures differently, and I'm not aware of any single tool which will function this way on both platforms. That said, you can perhaps write scripts that are portable between both systems:
#!/usr/bin/env bash
if type xclip >/dev/null; then
clip_copy="xclip"
clip_paste="xclip -o"
elif type pbcopy >/dev/null ; then
clip_copy="pbcopy"
clip_paste="pbpaste"
else
echo "ERROR: no clipboard functions. Where am I?" >&2
exit 1
fi
Also note that pbcopy/pbpaste support different data types, whereas xclip just deals with text.
That said, both of these functions deal with stdin and stdout. If you want to actually simulate keypresses (as your edit appears to imply), you need another tool.
In the Mac world, a number of options exist. Cliclick works well for me. This tool has full mouse support, but also has an option t:, which will simulate keyboard input. It seems reasonable that one might cliclick t:"$(pbpaste)", though I've never tried it.
You can also use AppleScript to print arbitrary text:
$ osascript -e 'tell application "System Events" to keystroke "Hello world."'
In X, xdotool seems to work.
$ xdotool type "Hello world."
To make a script which might run in both macOS and X environments, you could key on the output of uname -s:
#!/usr/bin/env bash
case "$(uname -s)" in
Darwin)
clip_copy="pbcopy" # note: $clip_copy isn't used in this script.
clip_paste="pbpaste"
type_cmd="osascript -e 'tell application \"System Events\" to keystroke \"%s\"'"
;;
*)
clip_copy="xclip"
clip_paste="xclip -o"
type_cmd='xdotool type "%s"'
;;
esac
text="$($clip_paste)"
printf "$type_cmd" "${text//[!A-Za-z0-9. ]/}" | sh
Note: untested. YMMV. May contain nuts.
Based on a gist in the comments I found a thread on stack exchange that helped me answer my own question: https://unix.stackexchange.com/a/213821.
I am only interested in supporting sh, bash, zsh so the following solution works fine:
#!/bin/bash
if [ "$(echo $ZSH_VERSION)" ]; then
print -z $#
else
# assume bash or sh
bind '"\e[0n": "'"$*"'"'; printf '\e[5n'
fi
Call with source inject.sh echo foo

osascript using bash variable with a space

I am using osascript in Bash to display a message in Notification Center (Mac OS X) via Apple Script. I am trying to pass a text variable from Bash to the script. For a variable without spaces, this works just fine, but not for one with spaces:
Defining
var1="Hello"
var2="Hello World"
and using
osascript -e 'display notification "'$var1'"'
works, but using
osascript -e 'display notification "'$var2'"'
yields
syntax error: Expected string but found end of script.
What do I need to change (I am new to this)? Thanks!
You could try to use instead :
osascript -e "display notification \"$var2\""
Or :
osascript -e 'display notification "'"$var2"'"'
This fixes the problem of manipulation of variables that contains spaces in bash. However, this solution doesn't protect against injections of osascript code. So it would be better to choose one of Charles Duffy's solutions or to use bash parameter expansion :
# if you prefer escape the doubles quotes
osascript -e "display notification \"${var2//\"/\\\"}\""
# or
osascript -e 'display notification "'"${var2//\"/\\\"}"'"'
# if you prefer to remove the doubles quotes
osascript -e "display notification \"${var2//\"/}\""
# or
osascript -e 'display notification "'"${var2//\"/}"'"'
Thank to mklement0 for this very useful suggestion !
This version is completely safe against injection attacks, unlike variants trying to use string concatenation.
osascript \
-e "on run(argv)" \
-e "return display notification item 1 of argv" \
-e "end" \
-- "$var2"
...or, if one preferred to pass code in on stdin rather than argv:
osascript -- - "$var2" <<'EOF'
on run(argv)
return display notification item 1 of argv
end
EOF

What does ${1-1} in bash mean?

I'm reading the scripts from here and trying to understand what's going on. This function performs changing the directory of a Finder window:
function ee {
osascript -e 'set cwd to do shell script "pwd"'\
-e 'tell application "Finder"'\
-e "if (${1-1} <= (count Finder windows)) then"\
-e "set the target of window ${1-1} to (POSIX file cwd) as string"\
-e 'else' -e "open (POSIX file cwd) as string"\
-e 'end if' -e 'end tell';\
};\
I'm assuming the $ is interpreted by bash, since it's inside double-quotes. I haven't been able to find what could {1-1} mean. I've played with the expression in separate test scripts but couldn't find a difference from plain $1. Any ideas?
This means that if argument 1 (${1}) is not set, it will be set to 1.
See parameter substitution here.
${parameter-default}, ${parameter:-default}
If parameter not set, use default.

Convert AppleScript to one line

I'm using Mach Desktop to echo a script's results into a Desklet, so it has to be in this format:
echo 'tell application "iTunes" to return album of current track' | osascript
I have a single line in which to enter data, so the script needs to be one long string.
It may be that the entire thing must be contained within one set of single quotes after echo, as follows:
echo '[entire script]' | osascript
How do I convert the AppleScript below to one line?
set some_file to "Macintosh HD:Users:Zade:Library:Application Support:Notational Data:Words.txt" as alias
set the_text to read some_file as string
set the text item delimiters of AppleScript to ", "
set the_lines to (every text item of the_text)
return some item of the_lines
Here is what I'm trying:
echo 'set some_file to "Macintosh HD:Users:Zade:Library:Application Support:Notational Data:Words.txt" as alias -e set the_text to read some_file as string -e set the text item delimiters of AppleScript to ", " -e set the_lines to (every text item of the_text) -e return some item of the_lines' | osascript
And that gives this error:
107:112: syntax error: A "set" can't go after this identifier. (-2740)
I suppose you could try out this script. I'm confused as to what you're actually trying to accomplish, though, so I apologize if this script is unsatisfactory.
echo 'set some_file to "~/Library/Application Support/Notational Data/Words.txt" as POSIX file as alias' -e 'set the_text to read some_file' -e 'set the text item delimeters of AppleScript to ","' -e 'set the lines to (every text item of the_text)' -e 'return the lines' | osascript
EDIT: #Zade That would be because Words.txt doesn't exist. Aliases only refer to existing files. Therefore, you must choose a file that exists. Here is an easy way to see what the correct syntax is for file references:
set some_file to (choose file)
You will notice that the file path is delimited by colons ( : ) rather than slashes. Having said this, choose a file that exists, and run your script with that file.

Resources