Cannot open a file with Applescript - applescript

I'm following the same instruction as listed on this page
https://discussions.apple.com/thread/7761153?login=true
and yet I cannot open this text file
tell application
"TextEdit" open file "Macintosh HD:Users:kylefoley:codes:byu_docs:dictionaries:first_name_research:btn_tree_start_r.rtxt"
end tell
The error message I'm getting is: Expected “given”, “with”, “without”, other parameter name, etc. but found class name.
Ultimately I need to be open it with a python script. So when I use Python I get a different error message:
file='Macintosh HD:Users:kylefoley:codes:byu_docs:dictionaries:first_name_research:btn_tree_start_r:Jaxson.rtxt'
os.system(
... f'''/usr/bin/osascript -e
... 'tell application
... "TextEdit" open file "{file}"
... end tell' ''')
/usr/bin/osascript: option requires an argument -- e
usage: osascript [-l language] [-e script] [-i] [-s {ehso}] [programfile] [argument ...]
sh: line 3: tell application
"TextEdit" open file "Macintosh HD:Users:kylefoley:codes:byu_docs:dictionaries:first_name_research:btn_tree_start_r:Jaxson.rtxt"
end tell: command not found
I should also add that I'm certain the file exists because when I put in a bogus file I get the following error message: No such file or directory
++++++++++++++++++
UPDATE
+++++++++++++++++
Ok, I can open it with Script Debugger but that's useless because I need to be able to execute the apple script with Python. When I run
tell application "TextEdit"
open file "Macintosh HD:Users:kylefoley:codes:byu_docs:dictionaries:first_name_research:btn_tree_start_r:Jaxson.rtxt"
end tell
On Script Debugger it works. But the Python syntax:
os.system(
... f'''/usr/bin/osascript -e
... 'tell application "TextEdit"
... open file "{file}"
... end tell' ''')
/usr/bin/osascript: option requires an argument -- e
usage: osascript [-l language] [-e script] [-i] [-s {ehso}] [programfile] [argument ...]
sh: line 3: tell application "TextEdit"
open file "Macintosh HD:Users:kylefoley:codes:byu_docs:dictionaries:first_name_research:btn_tree_start_r:Jaxson.rtxt"
end tell: command not found
Also, the following fails:
os.system(
... f'''/usr/bin/osascript -e 'tell application "TextEdit" open file "{file}" end tell' ''')
28:32: syntax error: Expected end of line but found command name. (-2741)
os.system(
... f'''/usr/bin/osascript -e 'tell application "TextEdit" open file "{file}" ' ''')
28:32: syntax error: Expected end of line but found command name. (-2741)
I know Python can use Applescript because the following works:
os.system(
f'''/usr/bin/osascript -e 'tell app "TextEdit" to save (every window whose name is "{file}")' ''')

State what the Applescript is in the variable script such as:
from subprocess import Popen, PIPE
file = 'hey_you.rtxt"
script = f'''
tell application "TextEdit"
open file "{file}"
end tell
'''
Then:
p = Popen(['osascript', '-'], stdin=PIPE, stdout=PIPE, stderr=PIPE, universal_newlines=True)
...stdout, stderr = p.communicate(script)

Related

mac unix: Get name of terminal I am using through commands

I am looking for a terminal command that will open a new tab in the current terminal that I am using. For example, I run the command in iTerm 2 and a new tab opens in iTerm2 because that is the terminal that i am using.
I know how to open a tab by naming a static application like so:
osascript -e 'tell application "iTerm" to activate' \
-e 'tell application "System Events" to tell process "iTerm" to keystroke "t" using command down'
But of course this still opens iTerm if I am doing something like calling the command from mac's Terminal. I would love to do something like below, but I am unsure how to get the name of the terminal I am using.
currentTerminal = getCurrentTerminalApplicationName()
osascript -e 'tell application "&{currentTerminal}" to activate' \
-e 'tell application "System Events" to tell process "&{currentTerminal}" to keystroke "t" using command down'
I am also open to other ideas.
While inside macOS terminal:
env | grep TERM
TERM_PROGRAM=Apple_Terminal
While inside iTerm2:
env | grep TERM
TERM_PROGRAM=iTerm.app
UPDATE
You can always do something like this:
#!/bin/bash
if [ "$TERM_PROGRAM" == "iTerm.app" ]; then
echo "iTerm2"
cat <<EOF >/tmp/file.py
import iterm2
async def main(connection):
app = await iterm2.async_get_app(connection)
window = app.current_terminal_window
if window is not None:
await window.async_create_tab()
else:
print("No current window")
iterm2.run_until_complete(main)
EOF
$HOME/Library/Application\ Support/iTerm2/iterm2env-3.10/versions/3.10.4/bin/python /tmp/file.py
else
echo "not iTerm2"
fi
This code will open new tab inside iTerm2 - otherwise, it will do nothing.

Using bash for loops in conjunction with embedded applescript for bash scripts

I'm trying to get applescript to interact with the bash for loop that is a part of my code to keep from having to list each host manually and execute individual tell/end tell blocks for each host found in the hosts2.txt file.
The purpose of the script is to open a new terminal tab on my Mac and automatically launch "screen -r $HOST" in each new terminal until the end of the list of hosts in the hosts2.txt document. Each host is listed on its own line.
I've tried an all inclusive for loop, without the applescript "repeat 2 times" "end repeat" code that is shown below. It is repeating 2 times because there are only 2 hosts listed in the text document for testing purposes. Each time I have error output.
#!/bin/bash
for HOST in `cat ~/bin/hosts2.txt`
do echo $HOST
osascript -e 'repeat 2 times
tell application "Terminal" activate
tell application "System Events" to keystroke "t" using [command down]
tell application "Terminal" to activate
set host to $HOST
tell application "Terminal"
do shell script "screen -r " & host in front window
end tell
end repeat'
done
What I expect to happen is for the code the execute opening new terminal tabs with screen -r for each host. Error output is below this line.
dev
44:52: syntax error: Expected end of line but found command name. (-2741)
pulsar
44:52: syntax error: Expected end of line but found command name. (-2741)
There are a few issues with your script: some that stop it from working entirely; some that get it to do the wrong thing; and some that needn't have been there in the first place. There are couple of other answers that address some points, but neither of them appeared to test the script because there's a lot they don't address.
...for each host found in the hosts2.txt file...
...Each host is listed on its own line.
Then this line:
for HOST in `cat ~/bin/hosts2.txt`
is not what you want. That will create an array out of individual words, not lines in the file. You want to use the read command, that reads a file line-by-line. You can structure a loop in this manner:
while read -r HOST; do
.
.
.
done < ~/bin/hosts2.txt
As #entraz has already pointed out, your use of single quotes will stop shell variables from being expanding within your osascript.
Then there is the AppleScript itself.
I'm unclear why you included a repeat loop.
The purpose of the script is to open a new terminal tab on my Mac and automatically launch "screen -r $HOST" in each new terminal until the end of the list of hosts in the hosts2.txt document. Each host is listed on its own line.
It is repeating 2 times because there are only 2 hosts listed in the text document
This makes no sense, given that you implemented a bash loop in order to read the lines into the $HOST variable. Granted, you were reading words, not lines, but the AppleScript repeat is a head-scratcher. Bin it.
Then you have this:
tell application "Terminal" activate
tell application "System Events" to keystroke "t" using [command down]
tell application "Terminal" to activate
That's approximately infinity times the number you need to tell Terminal to activate.
This line:
set host to $HOST
will throw an error for two reasons: firstly, host is taken as an existing name of a property in AppleScript's standard additions, so you can't go and set it to a new value; secondly, there are no quotes around $HOST, so it's not going to be recognised as a string. But, this is just for your learning, as we're actually going to get rid of that line completely.
Finally:
tell application "Terminal"
do shell script "screen -r " & host in front window
end tell
is wrong. do shell script is not a Terminal command. It's a command belonging to AppleScript's standard additions. Therefore, if the rest of your code worked, and it got to this command, Terminal would execute nothing. Instead, the shell scripts would run in the background without an actual shell, so that's not much good to you.
The command you're after is do script.
Sadly, it does appear that, in High Sierra at least, the AppleScript commands to make new tabs and windows in Terminal no longer work, so I can see why you resorted to System Events to create a tab in the way that you have. Thankfully, that's not necessary, and nor are your multiple activate commands: do script will automatically run Terminal and execute a script in a new tab by default.
Therefore, the only AppleScript command you need is this:
tell application "Terminal" to do script "screen -r $HOST"
The Final Script
Putting this all together, here is the final hybrid script:
while read -r HOST; do
echo "$HOST"
osascript -e "tell application \"Terminal\" to do script \"screen -r $HOST\""
done < ~/bin/hosts2.txt
Alternatively
If you wanted to take the loop from bash and put it in AppleScript instead, you can do so like this, for which I'll use a heredoc (<<) to simplify the use of quotes and aid readability:
osascript <<OSA
property home : system attribute "HOME"
property file : POSIX file (home & "/bin/hosts2.txt")
set hosts to read my file using delimiter {return, linefeed}
repeat with host in hosts
tell application "Terminal" to do script ("screen -r " & host)
end repeat
OSA
You have a typo in your code.
The line tell application "Terminal" activate should be tell application "Terminal" to activate.
Variable expansion also doesn't work in single quotes in bash (single quotes means everything is interpreted literally), so the line set host to $HOST within the single quotes won't work.
Try this:
#!/bin/bash
for HOST in `cat ~/bin/hosts2.txt`
do echo $HOST
osascript -e "repeat 2 times
tell application \"Terminal\" to activate
tell application \"System Events\" to keystroke \"t\" using [command down]
tell application \"Terminal\" to activate
set host to \"$HOST\"
tell application \"Terminal\"
do shell script \"screen -r \" & host in front window
end tell
end repeat"
done
Edit: I think there's actually another problem: when setting a variable to a string in applescript, the string needs to be enclosed in quotes. So set host to $HOST causes an error because it interprets the value of $HOST ("pulsar" or "dev") as a command that it's unable to find/execute; it needs to be set host to \"$HOST\" instead. I've changed it above.
You might find a here-doc to be readable and easy to work with. Also, use a while-read loop to iterate over the lines of a file (ref: http://mywiki.wooledge.org/BashFAQ/001)
while read -r host; do
echo "$host"
osabody=$(cat << END_OSA
repeat 2 times
tell application "Terminal" to activate
tell application "System Events" to keystroke "t" using [command down]
tell application "Terminal" to activate
set host to "$host"
tell application "Terminal"
do shell script "screen -r " & host in front window
end tell
end repeat
END_OSA
)
osascript -e "$osabody"
done < ~/bin/hosts2.txt
The ending parenthesis of the $(cat ... command substitution has to be on a separate line because the terminating word of the heredoc must be the only characters on that line.

Shell script for closing all apps open dock via command line

I'd like to run a script to close all apps currently open in my doc. Figured out how to do with with the following script, where APPLICATIONNAME is the name of the app in the dock currently open
osascript -e 'quit app "APPLICATIONNAME"'
Any ideas on how to expand this command to encompass all apps open inside the doc?
Ideally we'd avoid using a killall flavor of script. As force closing running apps in bulk will pose risks in some circumstances
Firstly there is no terse solution to achieve this using osascript as described in your question. osascript by itself simply doesn't provide the options/arguments necessary to fulfil the logic of your requirement.
However, the following bash shell script (.sh) avoids using killall and will prompt the user to save any unsaved changes to document(s) before closing/quitting the application. (This is very similar to how the user is prompted to save any unsaved changes when shutting down the computer):
close-apps.sh
#!/bin/bash
# Creates a comma-separated String of open applications and assign it to the APPS variable.
APPS=$(osascript -e 'tell application "System Events" to get name of (processes where background only is false)')
# Convert the comma-separated String of open applications to an Array using IFS.
# http://stackoverflow.com/questions/10586153/split-string-into-an-array-in-bash
IFS=',' read -r -a myAppsArray <<< "$APPS"
# Loop through each item in the 'myAppsArray' Array.
for myApp in "${myAppsArray[#]}"
do
# Remove space character from the start of the Array item
appName=$(echo "$myApp" | sed 's/^ *//g')
# Avoid closing the "Finder" and your CLI tool.
# Note: you may need to change "iTerm" to "Terminal"
if [[ ! "$appName" == "Finder" && ! "$appName" == "iTerm" ]]; then
# quit the application
osascript -e 'quit app "'"$appName"'"'
fi
done
Note: In the following line of code we avoid closing the Finder and the CLI tool that the command will be run via. You will probably need to change "iTerm" to "Terminal", or to whatever the name of your CLI tool is:
if [[ ! "$appName" == "Finder" && ! "$appName" == "iTerm" ]]; then
Making close-apps.sh executable
As explained in this answer you will need to make the close-apps.sh executable before it can be run. To do this enter the following via your CLI:
$ chmod +x /path/to/close-apps.sh
(The /path/to/close-apps.sh part should be replaced with your path according to where the script is saved)
Running close-apps.sh via the CLI.
You run the shell script by entering the following into the CLI:
$ /path/to/close-apps.sh
(Again, the /path/to/close-apps.sh part should be replaced with your path according to where the script is saved)
Running close-apps.sh via an Applescript.
The shell script can also be executed via an AppleScript application simply by double-clicking instead of entering a command via the CLI.
To do this you'll need to:
Open the AppleScript Editor application, which can be found inside the Applications/Utilities/ folder.
Enter the following code:
on run
do shell script "/path/to/close-apps.sh"
quit
end run
(Again, the /path/to/close-apps.sh part should be replaced with your path according to where the .sh script is saved)
Save the Applescript and chose File Format: Application via the save dialog. Let's call it closeApps.app.
Finally, the following line of code in the close-apps.sh script should be changed from this:
if [[ ! "$appName" == "Finder" && ! "$appName" == "iTerm" ]]; then
... to this:
if [[ ! "$appName" == "Finder" && ! "$appName" == "closeApps" ]]; then
Note The filename of the Applescript (closeApps) replaces iTerm (or Terminal).
To close all applications open in the dock you simply double click the closeApps application icon.
Try this
tell application "System Events"
set appList to the name of every process whose background only is false
end tell
repeat with theApp in appList
try
tell application theApp to quit
end try
end repeat

How to indent applescript when running in bash script?

osascript -e "set x to 3"
osascript -e "if x is 5 then"
osascript -e " tell application \"System Events\" to keystroke return"
osascript -e "end if"
The output i get
14:14: syntax error: Expected end of line but found end of script. (-2741)
0:6: syntax error: A “if” can’t go after this “end”. (-2740)
Can't see whats wrong with the script. Might be some issue with indentation. Anyone used osascript inside bash files ?
Put all your applescript lines together. This way:
osascript -e "set x to 3
if x is 5 then
tell application \"System Events\" to keystroke return
end if"
Additionally, you can create a file like the following with all your applescript code:
#!/usr/bin/osascript
set x to 3
if x is 5 then
tell application "System Events" to keystroke return
end if
I find this way easiest in respect of quoting and double-quoting and escaping, and using bash variables in the osascript:
#!/bin/bash
# Set bash variable to 3, then use it in osascript
count=3
osascript <<EOF
beep $count
tell application "Safari"
set theURL to URL of current tab of window 1
end tell
EOF
# Continue in bash
echo done

How can I edit itunes song lyrics from the terminal?

I can get the lyrics using:
osascript -e '''tell application "iTunes" to lyrics of the current track'''
but how can I set them?
I'm trying to make corrections to the current lyrics using my text editor.
osascript -e 'tell application "iTunes" to set lyrics of current track to "hoho"'
Thanks to regulus6633
And as a cli script
#!/usr/bin/env osascript
-- update_lyrics <track persisten ID> <lyric file>
on run argv
try
set trackPersistentID to item 1 of argv
set lyricsFile to item 2 of argv
-- use awk to strip leading empty lines
set cmdString to "cat " & lyricsFile & " | awk 'p;/^#+$/{p=1}'"
set newLyrics to do shell script cmdString
on error
return "update_lyrics <trackID> <lyricsFile>"
end try
tell application "iTunes"
set mainLibrary to library playlist 1
try
set foundTrack to (first file track of mainLibrary whose persistent ID = trackPersistentID)
set lyrics of foundTrack to newLyrics
on error err_mess
log err_mess
end try
end tell
end run

Resources