Check whether disk exists in applescript - applescript

I'm making an apple script to unmount a volume when I don't need it and then mount it again once I click on the application...
Im creating it in automator and the code looks like this:
if disk "UNIVERSAL" exists then
do shell script "diskutil unmount /volumes/UNIVERSAL"
else
do shell script "diskutil mount /volumes/UNIVERSAL"
end if
I get an error at the disk "UNIVERSAL" exists please help...
Thanks
Ben

Is the if statement within a tell application "Finder" block?
tell application "Finder"
if disk "Mac OS X" exists then
beep
end if
end tell

An alternative to using the Finder is this...
set diskName to "UNIVERSAL"
if diskName is in (do shell script "/bin/ls /Volumes") then
-- unmount
else
-- mount
end if

Checking if folder exists is not really safe, what if a previous mount failed?
What if there is a directory mounted UNIVERSAL-1 or UNIVERSAL MOVIES... etc
A more secure and more close alternative to the Finder would be
set theVolume to "/Volumes/UNIVERSAL"
set mountedVolumes to every paragraph of (do shell script "mount | awk -F' on ' '{print $2}' | awk -F' \\\\(' '{print $1}'")
if theVolume is in mountedVolumes then
--Volume is mounted
else
--volume is not mounted
end if

Related

Applescript: list dev nodes of mounted and not mounted disks

Is it possible to get a list of dev nodes for disks using applescript? I found the system events application but cannot find the /dev entries there (like "/dev/disk1s1 on /"). I need something like 'mount' command but for the applescript.
System Events doesn't provide information about connected but unmounted disks.
You need to use the shell. To get the dev node use
set diskName to "MyVolume"
set devNode to do shell script "diskutil list | awk '/ " & diskName & " / {print $NF}'"
To mount a volume by name use
set diskName to "MyVolume"
do shell script "diskutil mount `diskutil list | awk '/ " & diskName & " / {print $NF}'`"

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

Tell an AppleScript to Restart Itself

I have an AppleScript saved as an application. When first run, it asks the user if they want to move it to the Applications folder. What I would like to be able to do is, after it's been moved, have the script quit itself and then reopen.
Obviously I can't say
tell me to quit
tell me to activate
...because it would stop running after the quit command.
Any suggestions?
Just run the script from inside the script, and make sure to terminate the current running of it with a return (can skip the actual return command if it's the last line of the script
-- do stuff
display dialog "Here I am again"
-- set alias to the script
-- run the script
set myScript to path to me
run script myScript
-- end current iteration
return
You can break out of this script by canceling the dialog, but you'll probably want to set a condition to check whether to run the script again.
Here's how I'd do this. Basically, You check if the application is running from the Applications folder. If it isn't, move it there, open another instance, and quit. Seems to work flawlessly. The activate in the beginning is because it seems that the application doesn't always move itself to the foreground:
--incase the application doesn't do this automagically
activate
set my_path to POSIX path of (path to me)
if my_path does not start with "/Applications/" then
set new_path to "/Applications/" & quoted form of (my name & ".app")
--"mv" wont move the application into the new location if it exists
try
do shell script "rm -rf " & new_path
end try
do shell script "mv -f " & quoted form of my_path & " " & new_path
do shell script "open -n " & new_path & " &> /dev/null &"
quit
end if
What I am doing.
First I enabled at by running the following command in Terminal (this only has to be done once)
sudo launchctl load -w /System/Library/LaunchDaemons/com.apple.atrun.plist
then I have the following script
display dialog "running"
set mypath to POSIX path of (path to me)
set lun to open for access POSIX file "/tmp/springboard" with write permission
write "open " & mypath & linefeed to lun
close access lun
do shell script "at -f /tmp/springboard +1 minute"
quit

End Service if already running on Mac

I'm trying to create an Automator service that allows me to speak selected text.
I want to be able to use a keyboard shortcut, however, I also want to use a keyboard shortcut to end the service before it finishes.
I cannot figure out how to make the service stop once started running.
Here is my applescript code in Automator:
on run {input, parameters}
say input using "Alex" speaking rate 400
return input
end run
I know you can speak text in system prefs. But it maxes out at 300 wpm. I need this to do more than 300. Hence the Automator service.
Thanks for your help.
Another way should be to start saying nothing.
say "" stopping current speech true
If executed it will stop the current say output.
It's possible by getting the pid of the service, just write the pid to a temporary file.
When you want to stop the speaking, the script get the pid in the temporary file to quit this process ID.
on run {input, parameters}
set tFile to POSIX path of (path to temporary items as text) & "__auto_Runner_Speak_text__last_Pid__.txt"
try
set lastPid to word 1 of (read tFile) -- get the pid of the last speak text
if lastPid is not "" then
set tPids to words of (do shell script "/bin/ps -Axcro pid,command | sed -n '/Automator Runner/s/^ \\([0-9]*\\).*/\\1/p'")
if lastPid is in tPids then
do shell script "echo '' > " & (quoted form of tFile) & ";/bin/kill " & lastPid & " > /dev/null 2>&1 &" -- empty the file and stop the speaking
return -- quit this service
end if
end if
end try
do shell script "echo $PPID > " & quoted form of tFile -- write the PID of this workflow to the temp file
say input using "Alex" speaking rate 400
do shell script "echo '' > " & quoted form of tFile -- remove the PID of this workflow in the temp file
end run
Basically you'll have to kill the speech synthesis process...
try
set thePID to word 1 of (do shell script "/bin/ps -Axcro pid,command | grep speechsynthesis")
do shell script "kill -15 " & thePID
end try

Running a command in a new Mac OS X Terminal window

I've been trying to figure out how to run a bash command in a new Max OS X Terminal.app window. As, an example, here's how I would run my command in a new bash process:
bash -c "my command here"
But this reuses the existing terminal window instead of creating a new one. I want something like:
Terminal.app -c "my command here"
But of course this doesn't work. I am aware of the "open -a Terminal.app" command, but I don't see how to forward arguments to the terminal, or even if I did what arguments to use.
one way I can think to do it off the top of my head is to create a .command file and run it like so:
echo echo hello > sayhi.command; chmod +x sayhi.command; open sayhi.command
or use applescript:
osascript -e 'tell application "Terminal" to do script "echo hello"'
although you'll either have to escape a lot of double quotes or not be able to use single quotes
Partial solution:
Put the things you want done in a shell-script, like so
#!/bin/bash
ls
echo "yey!"
And don't forget to 'chmod +x file' to make it executable. Then you can
open -a Terminal.app scriptfile
and it will run in a new window. Add 'bash' at the end of the script to keep the new session from exiting. (Although you might have to figure out how to load the users rc-files and stuff..)
I've been trying to do this for a while. Here is a script that changes to the same working directory, runs the command, and closes the terminal window.
#!/bin/sh
osascript <<END
tell application "Terminal"
do script "cd \"`pwd`\";$1;exit"
end tell
END
In case anyone cares, here's an equivalent for iTerm:
#!/bin/sh
osascript <<END
tell application "iTerm"
tell the first terminal
launch session "Default Session"
tell the last session
write text "cd \"`pwd`\";$1;exit"
end tell
end tell
end tell
END
Here's yet another take on it (also using AppleScript):
function newincmd() {
declare args
# escape single & double quotes
args="${#//\'/\'}"
args="${args//\"/\\\"}"
printf "%s" "${args}" | /usr/bin/pbcopy
#printf "%q" "${args}" | /usr/bin/pbcopy
/usr/bin/open -a Terminal
/usr/bin/osascript -e 'tell application "Terminal" to do script with command "/usr/bin/clear; eval \"$(/usr/bin/pbpaste)\""'
return 0
}
newincmd ls
newincmd echo "hello \" world"
newincmd echo $'hello \' world'
see: codesnippets.joyent.com/posts/show/1516
Here's my awesome script, it creates a new terminal window if needed and switches to the directory Finder is in if Finder is frontmost. It has all the machinery you need to run commands.
on run
-- Figure out if we want to do the cd (doIt)
-- Figure out what the path is and quote it (myPath)
try
tell application "Finder" to set doIt to frontmost
set myPath to finder_path()
if myPath is equal to "" then
set doIt to false
else
set myPath to quote_for_bash(myPath)
end if
on error
set doIt to false
end try
-- Figure out if we need to open a window
-- If Terminal was not running, one will be opened automatically
tell application "System Events" to set isRunning to (exists process "Terminal")
tell application "Terminal"
-- Open a new window
if isRunning then do script ""
activate
-- cd to the path
if doIt then
-- We need to delay, terminal ignores the second do script otherwise
delay 0.3
do script " cd " & myPath in front window
end if
end tell
end run
on finder_path()
try
tell application "Finder" to set the source_folder to (folder of the front window) as alias
set thePath to (POSIX path of the source_folder as string)
on error -- no open folder windows
set thePath to ""
end try
return thePath
end finder_path
-- This simply quotes all occurrences of ' and puts the whole thing between 's
on quote_for_bash(theString)
set oldDelims to AppleScript's text item delimiters
set AppleScript's text item delimiters to "'"
set the parsedList to every text item of theString
set AppleScript's text item delimiters to "'\\''"
set theString to the parsedList as string
set AppleScript's text item delimiters to oldDelims
return "'" & theString & "'"
end quote_for_bash
I made a function version of Oscar's answer, this one also copies the environment and changes to the appropriate directory
function new_window {
TMP_FILE=$(mktemp "/tmp/command.XXXXXX")
echo "#!/usr/bin/env bash" > $TMP_FILE
# Copy over environment (including functions), but filter out readonly stuff
set | grep -v "\(BASH_VERSINFO\|EUID\|PPID\|SHELLOPTS\|UID\)" >> $TMP_FILE
# Copy over exported envrionment
export -p >> $TMP_FILE
# Change to directory
echo "cd $(pwd)" >> $TMP_FILE
# Copy over target command line
echo "$#" >> $TMP_FILE
chmod +x "$TMP_FILE"
open -b com.apple.terminal "$TMP_FILE"
sleep .1 # Wait for terminal to start
rm "$TMP_FILE"
}
You can use it like this:
new_window my command here
or
new_window ssh example.com
A colleague asked me how to open A LOT of ssh sessions at once. I used cobbal's answer to write this script:
tmpdir=$( mktemp -d )
trap '$DEBUG rm -rf $tmpdir ' EXIT
index=1
{
cat <<COMMANDS
ssh user1#host1
ssh user2#host2
COMMANDS
} | while read command
do
COMMAND_FILE=$tmpdir/$index.command
index=$(( index + 1 ))
echo $command > $COMMAND_FILE
chmod +x $COMMAND_FILE
open $COMMAND_FILE
done
sleep 60
By updating the list of commands ( they don't have to be ssh invocations ), you will get an additional open window for every command executed. The sleep 60 at the end is there to keep the .command files around while they are being executed. Otherwise, the shell completes too quickly, executing the trap to delete the temp directory ( created by mktemp ) before the launched sessions have an opportunity to read the files.
Another option that needs to be here is "ttab"
https://www.npmjs.com/package/ttab
Install
npm install ttab -g
Usage : Open another tab and run ls
ttab ls
Usage 2 : Open new tab, with Green BG, with title "hi", in directory ~/dev, and run code .
ttab -s Grass -t hi -d '~/dev' code .
I call this script trun. I suggest putting it in a directory in your executable path. Make sure it is executable like this:
chmod +x ~/bin/trun
Then you can run commands in a new window by just adding trun before them, like this:
trun tail -f /var/log/system.log
Here's the script. It does some fancy things like pass your arguments, change the title bar, clear the screen to remove shell startup clutter, remove its file when its done. By using a unique file for each new window it can be used to create many windows at the same time.
#!/bin/bash
# make this file executable with chmod +x trun
# create a unique file in /tmp
trun_cmd=`mktemp`
# make it cd back to where we are now
echo "cd `pwd`" >$trun_cmd
# make the title bar contain the command being run
echo 'echo -n -e "\033]0;'$*'\007"' >>$trun_cmd
# clear window
echo clear >>$trun_cmd
# the shell command to execute
echo $* >>$trun_cmd
# make the command remove itself
echo rm $trun_cmd >>$trun_cmd
# make the file executable
chmod +x $trun_cmd
# open it in Terminal to run it in a new Terminal window
open -b com.apple.terminal $trun_cmd
You could also invoke the new command feature of Terminal by pressing the Shift + ⌘ + N key combination. The command you put into the box will be run in a new Terminal window.

Resources