User Tools

Site Tools


action:Execute_a_Shell_Script

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
Next revision Both sides next revision
action:Execute_a_Shell_Script [2019/05/03 13:13]
JMichaelTX ADD example of Bash quoting
action:Execute_a_Shell_Script [2019/11/25 16:53]
JMichaelTX
Line 1: Line 1:
-{{:​action:​shell-script-icon.png?​nolink|}} 
 ====== Execute a Shell Script ====== ====== Execute a Shell Script ======
  
-The //Execute a Shell Script// action executes a specified shell script, either from a file or from the script embedded in the action.+The //Execute a Shell Script// action executes a specified shell script ​using `/bin/sh`, either from a file or from the script embedded in the action. 
 + 
 +**Important:​** 
 + 
 +* It is best to always specify the language using the `#!` at the front of the script. 
 +* The script is executed with the `sh` shell, so if you want to use another language, or use any special kinds of shell-specific syntax, then you should specify the language. 
 +* For more details and examples, see [[https://​forum.keyboardmaestro.com/​t/​impact-of-macos-catalina-defaulting-to-unix-shell-using-zsh/​15503/​12?​u=jmichaeltx|How to Use Shebang at Top of Shell Script]]
  
 To execute the script from an external file, choose the "​Execute Script File" in the choices for script location. To execute the script from an external file, choose the "​Execute Script File" in the choices for script location.
Line 9: Line 14:
  
 {{:​action:​execute-shell-script.png?​nolink&​693|}} {{:​action:​execute-shell-script.png?​nolink&​693|}}
 +
 +If the script fails, the action will fail (v9.0+), potentially aborting the macro.
 +
 +
  
 ==== Using Keyboard Maestro Variables ==== ==== Using Keyboard Maestro Variables ====
Line 24: Line 33:
 {{:​action:​km7-shell-script.png?​nolink|}} {{:​action:​km7-shell-script.png?​nolink|}}
  
-=== Python ===+==== Python ​====
  
 Accessing Keyboard Maestro Variables in Python is somewhat different. ​ Here is an example: Accessing Keyboard Maestro Variables in Python is somewhat different. ​ Here is an example:
Line 35: Line 44:
  
 See the [[#​Forum|Forum]] section below for more Python examples. See the [[#​Forum|Forum]] section below for more Python examples.
- 
---- 
  
 Note that you can only read these environment variables. ​ You cannot write to them (or more accurately, you can write to them but that will not change the Keyboard Maestro variables that they were created from). Note that you can only read these environment variables. ​ You cannot write to them (or more accurately, you can write to them but that will not change the Keyboard Maestro variables that they were created from).
 +
 +==== awk ====
 +
 +[Using shell variables in awk](https://​stackoverflow.com/​a/​15787068/​915019) is also different than in most other shell languages. ​ You need to pass the environment variable as parameter to the -v flag.
 +
 +Some examples:
 +
 +```bash
 +# EXAMPLE 1
 +
 +echo | awk -v my_var=4 '​{print "My var is " my_var}'​
 +#-->My var is 4
 +
 +# EXAMPLE 2
 +
 +VAR=3
 +echo | awk -v env_var="​$VAR"​ '​{print "The value of VAR is " env_var}'​
 +#-->The value of VAR is 3
 +
 +# USING KM VARIABLES with awk
 +
 +echo | awk -v env_var="​$KMVAR_My_KM_Variable"​ '​{print "The value of My_KM_Variable is: \""​env_var"​\""​}'​
 +#-->The value of My_KM_Variable is: "Text from KM var"
 +```
 +
 +For a KM Macro that shows this, see:\\
 +**[MACRO: ​  Using KM Variables with Bash awk [Example]](https://​forum.keyboardmaestro.com/​t/​passing-argument-to-awk/​16169/​3)**
  
 ==== Passing Paths in Variables ==== ==== Passing Paths in Variables ====
Line 73: Line 107:
   * [[https://​forum.keyboardmaestro.com/​t/​png-metadata-comment/​6375/​29| How To Quote Paths by @ccstone]].   * [[https://​forum.keyboardmaestro.com/​t/​png-metadata-comment/​6375/​29| How To Quote Paths by @ccstone]].
   * [[https://​forum.keyboardmaestro.com/​t/​trouble-expanding-variable-in-shell-script/​13664/​2?​u=jmichaeltx | Trouble Expanding Variable in Shell Script by @PeterNLewis]]   * [[https://​forum.keyboardmaestro.com/​t/​trouble-expanding-variable-in-shell-script/​13664/​2?​u=jmichaeltx | Trouble Expanding Variable in Shell Script by @PeterNLewis]]
- 
---- 
  
 ==== UTF-8 and Non-ASCII Characters ==== ==== UTF-8 and Non-ASCII Characters ====
  
 If you are dealing with non-ASCII characters, you probably want to set the `LC_ALL` environment variable to UTF8, which you can do by setting the Keyboard Maestro variable `ENV_LC_ALL` to “en_US.UTF-8”. If you are dealing with non-ASCII characters, you probably want to set the `LC_ALL` environment variable to UTF8, which you can do by setting the Keyboard Maestro variable `ENV_LC_ALL` to “en_US.UTF-8”.
 +
 +By default (v9.0+), if you have not set these environment variables they will be set to UTF-8 for you.
  
 ==== Action Gear ==== ==== Action Gear ====
  
-The Action ​(gear) menu includes the following options:+The action ​(gear) ​⚙ menu includes the following options:
  
 * Trim Results — removes white space from the start and end of the scripts results. * Trim Results — removes white space from the start and end of the scripts results.
Line 99: Line 133:
   * Pasted in to the current selection.   * Pasted in to the current selection.
   * Saved to a variable.   * Saved to a variable.
 +  * Appended to a variable (v9.0+).
   * Saved to the system or a Named Clipboard.   * Saved to the system or a Named Clipboard.
   * Asynchronously ignored — the action runs while the macro continues on.   * Asynchronously ignored — the action runs while the macro continues on.
Line 111: Line 146:
 ===== Quoting Strings ===== ===== Quoting Strings =====
  
-Proper quoting of strings in a Shell Script is often a challenge.+Proper quoting of strings in a Shell Script is often a challenge. ​ In order to understand it, you have to understand what happens at each level of the processing. 
 + 
 +Thankfully, in an Execute Script action, Keyboard Maestro itself does not do any processing, so that is one less place for confusion. 
 + 
 +With shell commands, the important thing to understand is that, with only a few exceptional programs, it is not the command that does the processing, it is the shell (bash usually, although there are many shells). 
 + 
 +So for example with Keyboard Maestro variable set to `"​Selection Style" -int 0` and en Execute Shell Script command of: 
 + 
 +```bash 
 +defaults write /​Users/​me/​Library/​Application\ Support/​Witch/​Settings $KMVAR_witchPref 
 +``` 
 + 
 +It is the *bash* tool that sees the string and it processes it in to an array of strings which it passes to the *defaults* tool.  This is important - the defaults command receives not a single string, but an array of strings, in this case the array will be: 
 + 
 +* `defaults` 
 +* `write` 
 +*  `/​Users/​me/​Library/​Application Support/​Witch/​Settings` 
 +* `"​Selection` 
 +* `Style"​` 
 +* `-int` 
 +* `0` 
 + 
 +It is bash that has processed the variable substitution for $KMVAR_witchPref,​ split the line in to seven parts, processed the backslash in "​Application\ Support"​ and then executed the defaults tool with the seven parts as arguments (the command itself is the 0th argument, normally mostly ignored by tools). 
 + 
 +So the problem is that the word-breaking,​ variable substitution,​ de-quoting and de-backslash is all happening at as the line is processed by bash, after which you are left with quotes from within variable substitution,​ but they no longer have any meaning, they are just characters. 
 + 
 +So variables that are meant to be a single parameter should be surrounded by double quotes in the line, but not contain quotes in the variable, and generally you do not want to pass multiple parameters within a single parameter. ​ So instead, perhaps set one variable to the setting name, and one variable to the type and one variable to the value, and then use a command like this: 
 + 
 +```bash 
 +defaults write "/​Users/​me/​Library/​Application Support/​Witch/​Settings"​ "​$KMVAR_Setting"​ -"​$KMVAR_Type"​ "​$KMVAR_Value"​ 
 +``` 
 + 
 +Now a further complication happens when you want to sent a string containing double quotes and variables to a parameter. ​ For example, perhaps you want a command like this: 
 + 
 +```bash 
 +emacsclient -e '​(w3m-browse-url "​$KMVAR_SafariURL"​)'​ 
 +``` 
 + 
 +This will not work because bash only expands variables within double-quoted strings. ​ Within single quoted strings, they remain as the text `$KMVAR_SafariURL` (unchanged). ​ And so emactsclient will receive the array: 
 + 
 +* `emacsclient` 
 +* `-e` 
 +* `(w3m-browse-url "​$KMVAR_SafariURL"​)` 
 + 
 +But it will not expand the variable (that is the shell’s job). 
 + 
 +To work around this you need to use either all double quotes (and backslash any double quotes within them) such as: 
 + 
 +```bash 
 +emacsclient -e "​(w3m-browse-url \"​$KMVAR_SafariURL\"​)"​ 
 +``` 
 + 
 +or use a combination of strings, some double quoted and some single quoted: 
 + 
 +```bash 
 +emacsclient -e '​(w3m-browse-url "'"​$KMVAR_SafariURL"'"​)'​ 
 +``` 
 + 
 +Note that that parameter is now made up of three stings combined into one parameter: ​
  
-For a discussion on how to quote a string, see this [[https://​forum.keyboardmaestro.com/​t/​having-trouble-with-quotes-and-shell-variables/​6236/​9 | Keyboard Maestro Forum post by @PeterNLewis]].+* `(w3m-browse-url "​` ​single quoted string 
 +* the value of $KMVAR_SafariURL ​double quoted string 
 +* `"​)` ​single quoted string
  
  
Line 124: Line 219:
 that is the script will search for tools in the `/usr/bin` directory, then in the `/bin` directory, then `/usr/sbin` and finally `/​sbin`. ​ Only tools installed by the system will be in these directories - any tools you have installed will almost certainly be elsewhere and so not found by default because: that is the script will search for tools in the `/usr/bin` directory, then in the `/bin` directory, then `/usr/sbin` and finally `/​sbin`. ​ Only tools installed by the system will be in these directories - any tools you have installed will almost certainly be elsewhere and so not found by default because:
  
-  * **shell scripts are executed in non-interactive mode** (see the INVOCATION section of the [bash man page](https://​developer.apple.com/​library/​mac/​documentation/​Darwin/​Reference/​ManPages/​man1/​bash.1.html)), the **only** path preset by default is the system path.+  * **shell scripts are executed in non-interactive mode** (see the INVOCATION section of the sh man page), the **only** path preset by default is the system path.
   * **Thus, your tools or files may not be automatically accessible.**   * **Thus, your tools or files may not be automatically accessible.**
   * The `$PATH` environment variable you may have set in Terminal is **not** used.   * The `$PATH` environment variable you may have set in Terminal is **not** used.
Line 213: Line 308:
 ==== Forum ==== ==== Forum ====
  
 +- [[https://​forum.keyboardmaestro.com/​t/​impact-of-macos-catalina-defaulting-to-unix-shell-using-zsh/​15503/​12?​u=jmichaeltx|How to Use Shebang at Top of Shell Script]]
 - [[https://​forum.keyboardmaestro.com/​t/​png-metadata-comment/​6375/​29|PNG Metadata "​Comment"​]] - [[https://​forum.keyboardmaestro.com/​t/​png-metadata-comment/​6375/​29|PNG Metadata "​Comment"​]]
 - [[https://​forum.keyboardmaestro.com/​t/​having-trouble-with-quotes-and-shell-variables/​6236/​9|Having trouble with quotes and shell variables]] - [[https://​forum.keyboardmaestro.com/​t/​having-trouble-with-quotes-and-shell-variables/​6236/​9|Having trouble with quotes and shell variables]]
action/Execute_a_Shell_Script.txt · Last modified: 2023/09/22 04:39 by peternlewis