How to make "which some_command" work from in an Applescript? - bash

I am writing an Applescript that uses sox, which is not available by default in MacOS X. I have everything working on my system, but I want the script to work for anyone else. Because the sox command is not where Applescript can automatically locate it, my hard coded 'do shell script' string must start with "/usr/local/bin/sox" instead of just "sox."
So, I need a way to locate sox, via Applescript, on any system. In terminal, "which sox" returns "/usr/local/bin/sox" without issue. In Applescript, "which sox" returns "sh: which sox: command not found." This is true for any command, not just sox.
I have tried every variation I can think of, without success. I will list every syntax I have used and the result I get. If anyone knows another/successful route to getting the path to sox from within an Applescript, PLEASE let me know.
Note that I have other shell commands (e.g. rm, mv, etc.) working in the script.
Lines that return "sh: which sox: command not found": (Note: I have also tried each with "which sox" replaced by which_sox, and a prior line to define which_sox as "which sox")
do shell script quoted form of "which sox"
do shell script (quoted form of "which sox") as text
do shell script (quoted form of "which sox") as string
tell current application to do shell script quoted form of "which sox"
tell current application to do shell script (quoted form of "which sox") as text
tell current application to do shell script (quoted form of "which sox") as string
Lines that return "sh: /bin/sh which sox: No such file or directory"
do shell script quoted form of "/bin/sh which sox"
do shell script (quoted form of "/bin/sh which sox") as text
do shell script (quoted form of "/bin/sh which sox") as string
tell current application to do shell script quoted form of "/bin/sh which sox"
tell current application to do shell script (quoted form of "/bin/sh which sox") as text
tell current application to do shell script (quoted form of "/bin/sh which sox") as string
(Note: I have also tried /bin/bash, /usr/local/bin/sh, and /usr/local/bin/bash both in "quotes" and as a defined which_sox variable.)
Yes, that is a LOT of methodical trial and (all) error to simply get the path of an installed command. Please forego any answers/suggestions for methods outside of Applescript as this must run as a script from within iTunes. Also, please attempt any proposal before posting it. I see a lot of 'answers' on this site that get replied to as 'your suggestion didn't work.'

I finally found a solution. The following returns the path to an installed BASH command (sox in this case):
tell me to set sox_path to (do shell script "eval $(/usr/libexec/path_helper -s); which sox")
If you want to know why this works, read AppleScript : error "sh: lame: command not found" number 127

quoted form of is only for variables. Since you have a literal command to execute, you simply need
do shell script "which sox"

Related

AppleScript do shell script returns error for "which" command

I'm writing an AppleScript that will ask a user which remote cloud service and then which bucket they would like to mount in Mac OS using rclone. But in order to run the rclone command in an AppleScript, you need to include the entire path to the app. For me that is: /usr/local/bin/rclone
I want to include, as a variable, the location of rclone using the which command in a shell script like this:
set rcloneLOC to paragraphs of (do shell script "which rclone")
But I get a script error stating "The command exited with a non-zero status." This happens even if I just try to run do shell script "which rclone" by itself. If I type which rclone into terminal, I get the result I expect.
How do I get this to work?
As #GordonDavisson suggests, you can view your path using echo $PATH.
To change your applescript's path (and view the change) try this:
do shell script "export PATH=/usr/local/bin:$PATH ; echo $PATH"
The first part of the shell command (up to the semi-colon) will prepend /usr/local/bin to your default path. The second part will return your updated path. The semi-colon has the second part run after the first part is finished.
It's important to note that this change is temporary and only in effect for this shell script and only while it is operating. This is why you need the combined commands in order to see the effect.
I'll use 'rsync' as an example since I don't have rclone; substitute 'rclone' to get its path. To get its path, you combine the export command with which, like so:
do shell script "export PATH=/usr/local/bin:$PATH ; which rsync"
The result is /usr/local/bin/rsync.
To clarify a couple of things… the environment is a set of conditions that apply for each user. You can get a basic rundown of it by running man 7 environ in Terminal. There is an env command which lists your settings and allows you to edit them; man env will provide info on it. At the bottom of these man pages, you should see references to related commands which you can also look up. Meanwhile, from within Script Editor, you could run a 1-line script with do shell script "env" and see the corresponding environment for applescript's shell.
Based on Apple's documentation (or my interpretation of it), they chose this setup because it is relatively secure and portable. You know what you get every time you run a shell script. You don't need to use a more modern shell to run the which command. You can modify the environment as needed, the same way you would while using the terminal.
Finally, Apple has provided Technical Note 2065 which provides info on using shell scripts with applescript. Also, you can likely get more info here or on the unix stack exchange.
NB All of the above is just my understanding, which is limited.

Passing Multiple Parameters from Applescript to Terminal Command Script

I have been trying to figure out how to pass multiple parameters from an Applescript to a Terminal Command Script. For example when running a terminal command file you are able to receive parameters programatically like so:
#!/bin/bash
var=$1
var=$2
The Applescript Code that I have been working with is below for reference:
tell application "System Events" to set app_directory to POSIX path of (container of (path to me))
set thisFile to "Dev"
set testTarget to "/Users/lab/Desktop/TestTarget/"
do shell script "/Users/lab/Desktop/TempRoot/mycommand.command " & thisFile & testTarget with administrator privileges
Where I think I have gone wrong is the input of the second parameter. When I only had one parameter it went through just fine:
do shell script "/path/to/command/mycommand.command" &var with administrative privileges
I am curious as to what the correct syntax would be for passing in this second parameter. If anybody has any suggestions please let me know! Also if you need more information I would be happy to provide it!
You just need to add a space between your arguments. Right now, there is no space being added between thisFile and testTarget. Your command looks like this:
/Users/lab/Desktop/TempRoot/mycommand.command Dev/Users/lab/Desktop/TestTarget/
Change your shell script line to:
do shell script "/Users/lab/Desktop/TempRoot/mycommand.command " & thisFile & space & testTarget with administrator privileges
Something that I find helpful when building a script is to make sure my shell commands are correct before running them. So instead of building it directly, store the command in a variable and log it. Later, replace the logging statement with the do shell script command.
set shellScript to "/Users/lab/Desktop/TempRoot/mycommand.command " & thisFile & space & testTarget with administrator privileges
log shellScript
-- do shell script shellScript

How can I use AppleScript to make Terminal.app run a shell script without evaluating the output as a script?

I'm using AppleScript to launch a quick-and-dirty shell script:
tell application "Terminal"
activate
do script "$(" & quoted form of MyScriptPath & ")"
end tell
Which properly launches a Terminal window and inputs what I would expect:
~$ $('/my script path/myscript.sh')
However, it seems that anything outputted to STDOUT (via echo) is evaluated as if it was inside the $( ) when evaluating/calling the script in the first place:
#!/bin/sh
echo "foobar"
produces:
-bash: foobar: command not found
I've searched far and wide and have not really found a suitable way to escape spaces in the path (rather than using "quoted form of") in AppleScript before sending the script location to Terminal, but I'd much prefer that. I'm using "do script" rather than "do shell script" because the script launching in Terminal is interactive and needs to be focused.
How can I echo to STDOUT when calling the script through $( )?
You don't need $(...) to run a command, only to include the output of that command in another string. You simply need
tell application "Terminal"
activate
do script "/my script path/myscript.sh"
end tell

Running a shell script through AppleScript

This is my first time trying to create a terminal script and then using AppleScript to run the code. I've tested my terminal script line by line in the terminal (it works...), but would like to put it in a file that can be called by applescript. So far, I've created a file called "/Applications/MAMP/htdocs/global_admin/import_database_command_line.sh" where I've saved all of the individual commands, the first being:
/Applications/MAMP/Library/bin/mysql --host=localhost -uroot -proot;
I then use AppleScript to call the script as:
do shell script
"/Applications/MAMP/htdocs/global_admin/import_database_command_line.sh"
Unfortunately, for each line in my script I get an error, such as:
error "/Applications/MAMP/htdocs/global_admin/import_database_command_line.sh:
line 1: : command not found
Any help in coordinating my AppleScript and the file that contains my shell commands would be appreciated.
You need to include #!/bin/sh in the top line of your .sh file
#!/bin/sh
echo "Hello, world!"
You then need to make the script executable:
chmod +x import_database_command_line.sh
This is because the 'do shell script' AppleScript command is expecting to run the shell commands contained within the quotes. It is not expecting to be calling another script as you are doing. Just put your commands within the quotes, separated by semi-colons.
do shell script "/Applications/MAMP/Library/bin/mysql --host=localhost -uroot -proot; #other_command; #etc"
Link

How to pass a variable FROM applescript TO a shell script?

I have the following script
#!/bin/bash
/usr/bin/osascript << EOT
set myfile to choose file
EOT
no_ext=$(python -c "print '$myfile'.split('.')[0]")
### this works - just need to know how to pass the arg
R CMD Sweave no_ext.Rnw
pdflatex no_ext.tex
open no_ext.pdf
Can anyone point me to "how to pass the variable myfile correctly" ?
EDIT
Thx for all the suggestions!
Don't know what to accept, all of your answers really helped me since I learned a lot from everybody.
The following problems exist in your script:
A variable set in the AppleScript section does become defined in the enclosing shell script. You have to do the data exchange with the shell script by using command substitution.
AppleScripts invoked from a shell script aren't allowed to do user interaction because they do not have an application context. You can use the helper application "AppleScript Runner" to run user interaction commands.
Here is a revised version of your script where those problems are fixed:
#!/bin/bash
myfile=$(/usr/bin/osascript << EOT
tell app "AppleScript Runner"
activate
return posix path of (choose file)
end
EOT)
if [ $? -eq 0 ]
then
echo $myfile
else
echo "User canceled"
fi
First, you need to get the contents of the myfile variable from Applescript to bash. I don't know Applescript, so I'll make a shot in the dark as to how to write to its standard output. Then the python part is just unnecessary complexity (and likely wrong anyway, you were throwing away everything after the first . rather than the last). Next you need a $ before the variable name in bash syntax. I think the following script does what you want:
#!/bin/sh
set -e
myfile=$(osascript <<EOT
set myfile to choose file
write myfile to stdout
EOT
)
no_ext="${myfile%.*}"
R CMD Sweave "$no_ext.Rnw"
pdflatex "$no_ext.tex"
open "$no_ext.pdf"
(set -e at the beginning makes the shell exit immediately if an error occurs, instead of trying to execute pdflatex even though no .tex file has been produced or somesuch.)
Realize that applescript paths are colon ":" delimited. You need slash delimited in bash so in applescript terms that's the "posix path". Also, when using osascript it can't open dialog windows. You must tell an application to open the window. Next, you "return" something from the applescript... that's what goes to bash. Finally, in bash to execute a command and assign the result to a variable use `` around the command. So knowing this here's a shell script to use an applescript to get the myFile variable.
#!/bin/bash
myFile=`/usr/bin/osascript << EOT
tell application "Finder"
activate
set myfile to choose file with prompt "Select the file to use in bash!"
end tell
return (posix path of myfile)
EOT`
echo $myFile

Resources