action:Execute_a_Shell_Script
Differences
This shows you the differences between two versions of the page.
| Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
| action:Execute_a_Shell_Script [2019/11/25 21:53] – JMichaelTX | action:Execute_a_Shell_Script [2025/09/12 07:02] (current) – [Quoting Strings] peternlewis | ||
|---|---|---|---|
| Line 7: | Line 7: | ||
| * It is best to always specify the language using the `#!` at the front of the script. | * 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. | * 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. | ||
| + | * The shell is a non-login shell, so configuration files (like .bashrc) will not be run - in particular, this means you will not have much in the PATH (see [[# | ||
| * For more details and examples, see [[https:// | * For more details and examples, see [[https:// | ||
| Line 17: | Line 18: | ||
| If the script fails, the action will fail (v9.0+), potentially aborting the macro. | If the script fails, the action will fail (v9.0+), potentially aborting the macro. | ||
| + | Keyboard Maestro sets the environment variables for the script to include all your variables, using a prefix of `KMVAR_` and your variable name with spaces changed in to underscores (‗). For example, your Keyboard Maestro “File Name” variable will be available as the environment variable `KMVAR_File_Name`. | ||
| + | Keyboard Maestro also provides (v10.0+) a number of environment variables that contain information about the executing macro. These include: | ||
| + | |||
| + | ^environment variable^meaning^ | ||
| + | |`KMINFO_MacroName`|The name of the parent executing macro| | ||
| + | |`KMINFO_MacroUUID`|The UUID of the parent executing macro| | ||
| + | |`KMINFO_MacroGroupName`|The name of the macro group containing the parent executing macro| | ||
| + | |`KMINFO_MacroGroupUUID`|The UUID of the macro group containing the parent executing macro| | ||
| + | |`KMINFO_ThisMacroName`|The name of the executing macro| | ||
| + | |`KMINFO_ThisMacroUUID`|The UUID of the executing macro| | ||
| + | |`KMINFO_ThisMacroGroupName`|The name of the macro group containing the executing macro| | ||
| + | |`KMINFO_ThisMacroGroupUUID`|The UUID of the macro group containing the executing macro| | ||
| + | |`KMINFO_TriggerTime`|The [[/ | ||
| + | |`KMINFO_TriggerBase`|The type of the trigger that started the parent macro| | ||
| + | |`KMINFO_Trigger`|The trigger description of the trigger that started the parent macro| | ||
| + | |`KMINFO_TriggerValue`|the value associated with how the parent macro was triggered| | ||
| + | |`KMINFO_ActionResult`|The success or failure of the immediate past action| | ||
| + | |`KMINFO_LastWindowID`|The window ID of the most recently displayed Keyboard Maestro Engine window| | ||
| + | |`KMINFO_PromptWithListText`|The text typed in the most recently executed [[action: | ||
| + | |`KMINFO_PasteByNameText`|The text typed in the most recently executed [[action: | ||
| ==== Using Keyboard Maestro Variables ==== | ==== Using Keyboard Maestro Variables ==== | ||
| - | === Most Languages like bash, perl, ruby === | + | Keyboard Maestro variables are included in the environment of the script, with the prefix `KMVAR_` and spaces in the name replaced with underscores (‗), |
| - | In your script, use this format: | + | By default, all variables are included, but you can select No Variables, or specific variables as desired using the popup menu next to the script (v11.0+). |
| - | where // | + | === Most Shell Languages like bash === |
| - | For example: | + | In your script, use this format $KMVAR‗*VARIABLE‗NAME* where *VARIABLE‗NAME* is the name of your Keyboard Maestro Variable, but with spaces in the name replaced with underscores (‗). |
| + | |||
| + | For example: | ||
| If your variable already has underscores, | If your variable already has underscores, | ||
| Line 33: | Line 56: | ||
| {{: | {{: | ||
| - | ==== Python ==== | + | Keep in mind that $KMVAR‗*VARIABLE‗NAME* is a shell environment variable, and this format is directly accessible to `bash`, `sh`, `zsh`, etc. Other languages may need a different method to read the shell environment variables. |
| - | Accessing | + | Note that you can only read these environment variables. |
| + | |||
| + | ==== Perl==== | ||
| + | |||
| + | ```perl | ||
| + | my $fileName = $ENV{KMVAR_File_Name}; | ||
| + | ``` | ||
| + | |||
| + | ==== Python ==== | ||
| ```python | ```python | ||
| # | # | ||
| + | |||
| import os | import os | ||
| - | print os.environ[' | + | print os.environ[' |
| ``` | ``` | ||
| See the [[# | See the [[# | ||
| - | |||
| - | Note that you can only read these environment variables. | ||
| ==== awk ==== | ==== awk ==== | ||
| - | [Using shell variables in awk](https:// | + | [Using shell variables in awk](https:// |
| Some examples: | Some examples: | ||
| ```bash | ```bash | ||
| - | # EXAMPLE 1 | + | awk -v awkVariable="$KMVAR_File_Name" 'BEGIN {print "The value of VAR is: " |
| - | + | ||
| - | echo | awk -v my_var=4 ' | + | |
| - | #-->My var is 4 | + | |
| - | + | ||
| - | # EXAMPLE 2 | + | |
| - | + | ||
| - | VAR=3 | + | |
| - | echo | awk -v env_var="$VAR" ' | + | |
| - | #-->The value of VAR is 3 | + | |
| - | + | ||
| - | # USING KM VARIABLES with awk | + | |
| - | + | ||
| - | echo | awk -v env_var=" | + | |
| - | #-->The value of My_KM_Variable is: "Text from KM var" | + | |
| ``` | ``` | ||
| - | |||
| - | For a KM Macro that shows this, see:\\ | ||
| - | **[MACRO: | ||
| - | |||
| ==== Passing Paths in Variables ==== | ==== Passing Paths in Variables ==== | ||
| If you are passing a file/folder path in a Keyboard Maestro Variable, then it is best to put the Variable reference in double quotes so that spaces in the path will work, like this: | If you are passing a file/folder path in a Keyboard Maestro Variable, then it is best to put the Variable reference in double quotes so that spaces in the path will work, like this: | ||
| + | |||
| ```bash | ```bash | ||
| cat " | cat " | ||
| Line 83: | Line 96: | ||
| **Consider These Guidelines** | **Consider These Guidelines** | ||
| - | * This must be a full path. **If the path starts with a tilde (~)**, then you must first convert it to a full path using the [[action: | + | * This must be a full path. **If the path starts with a tilde (~)**, then you must first convert it to a full path using the [[action: |
| * Like all Bash variables, the Keyboard Maestro Variable must _not_ be between single quotes (`'`) in order for the variable to be expanded to / replaced by its value. | * Like all Bash variables, the Keyboard Maestro Variable must _not_ be between single quotes (`'`) in order for the variable to be expanded to / replaced by its value. | ||
| ```bash | ```bash | ||
| # 🚫 Does NOT Work | # 🚫 Does NOT Work | ||
| - | / | + | echo 'The variable is "$KMVAR_File_Name"' |
| ``` | ``` | ||
| + | |||
| because although the Variable is between double-quotes, | because although the Variable is between double-quotes, | ||
| Line 96: | Line 110: | ||
| ```bash | ```bash | ||
| # ✅ This WORKS | # ✅ This WORKS | ||
| - | / | + | echo 'The variable is "'" |
| ``` | ``` | ||
| + | |||
| One key Bash feature that makes this work is that when two quoted strings are adjacent, they will be concatenated. | One key Bash feature that makes this work is that when two quoted strings are adjacent, they will be concatenated. | ||
| ```bash | ```bash | ||
| - | / | + | echo 'The variable is "Test.txt"' |
| ``` | ``` | ||
| - | |||
| - | For more info, see these discussions in the Keyboard Maestro Forum: | ||
| - | * [[https:// | ||
| - | * [[https:// | ||
| ==== UTF-8 and Non-ASCII Characters ==== | ==== UTF-8 and Non-ASCII Characters ==== | ||
| Line 120: | Line 131: | ||
| * 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. | ||
| * Include Errors — include stdout and stderr results from the script. | * Include Errors — include stdout and stderr results from the script. | ||
| - | |||
| ==== Output of Results ==== | ==== Output of Results ==== | ||
| Line 126: | Line 136: | ||
| The results of a shell script can be: | The results of a shell script can be: | ||
| - | * Ignored. | + | {{page> |
| - | * Displayed in a floating window. | + | |
| - | * Displayed briefly in a Notification. | + | If the output is going to a clipboard or a file, the downloaded data can be an image (v11.0+). |
| - | * Displayed large across | + | |
| - | * Typed in to the current selection. | + | If you want to return multiple values from a script, then you can use AppleScript (via `osascript`) to [[manual: |
| - | * Pasted in to the current selection. | + | |
| - | * Saved to a variable. | + | |
| - | * Appended to a variable | + | |
| - | * Saved to the system or a Named Clipboard. | + | |
| - | * Asynchronously ignored — the action runs while the macro continues on. | + | |
| - | If you want to return multiple values from a script, then you can either use AppleScript (via `osascript`) to [[manual: | ||
| ===== Examples ===== | ===== Examples ===== | ||
| Line 170: | Line 174: | ||
| It is bash that has processed the variable substitution for $KMVAR_witchPref, | It is bash that has processed the variable substitution for $KMVAR_witchPref, | ||
| - | So the problem is that the word-breaking, | + | So the problem is that the word-breaking, |
| 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 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. | ||
| Line 178: | Line 182: | ||
| ``` | ``` | ||
| - | Now a further complication happens when you want to sent a string containing double quotes and variables to a parameter. | + | Now a further complication happens when you want to send a string containing double quotes and variables to a parameter. |
| ```bash | ```bash | ||
| Line 210: | Line 214: | ||
| * `")` - single quoted string | * `")` - single quoted string | ||
| + | For the reverse problem, where you have a variable that contains multiple parameters, note that you cannot use quotes within a variable - by the time the shell is expanding variables, it has already processed quotes and will not do so again so quotes will just be regular characters passed to the target command and almost certainly result in errors. If possible, use seperate variables for seperate parameters, but if you cannot do that (for example you have a list of paths), store them as seperate lines in a variable (without any quoting or backslashes) and use a command like: | ||
| + | |||
| + | ```bash | ||
| + | echo " | ||
| + | ``` | ||
| + | |||
| + | The tr command will replace `\r` or `\n` line endings with a nul character, and the `xargs -0` command will read that, split the arguments at the nul character, and pass them to the specified command (in this case `ls -l`. Note that xargs has a limit to the number of arguments it will pass, so for large numbers of arguments it may run the command multiple times with subsets of the arguments - read the `xargs` man page for more details. | ||
| + | |||
| + | Also note that shell globing happens after variable expansion, and so if the variable contains `*` characters they will be expanded by the shell by matching file names in the current directory. To avoid this, you can turn off globing by using the -f option when executing bash - that is, start your script with `# | ||
| ===== Path in Shell Scripts ===== | ===== Path in Shell Scripts ===== | ||
| - | **In essence, the _default_ path in a Keyboard Maestro Execute Shell Script is the base path for the system:** | + | In essence, the _default_ path in a Keyboard Maestro Execute Shell Script is the base path for the system: |
| / | / | ||
| - | that is the script will search for tools in the `/usr/bin` directory, then in the `/bin` directory, then `/usr/sbin` and finally `/ | + | That is the script will search for tools in the `/usr/bin` directory, then in the `/bin` directory, then `/usr/sbin` and finally `/ |
| - | * **shell | + | * 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. |
| * 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. | ||
| - | * None of your profile scripts (like *~/.profile*) will be executed. | + | * None of your profile scripts (like `~/.profile`) will be executed. |
| * Custom environment variable settings will not be applied, including any settings for tool-specific environment variables like PERL5LIB. | * Custom environment variable settings will not be applied, including any settings for tool-specific environment variables like PERL5LIB. | ||
| - | **How To Set a Path** | + | Generally, |
| - | * If you need access to tools (executables) or files that you installed (not part of the system installation), | + | |
| - | * **Use an explicit, full path** to the tool or file.\\ See [[# | + | |
| - | * **Set the `$PATH` environment variable within each Execute Shell Script action**.\\ OR | + | |
| - | * **Set `ENV_PATH`** (the Keyboard Maestro Path Variable) **prior to the Execute Shell Script Action.** | + | |
| - | * The path defined in this Variable will automatically apply to every Execute Shell Script, without need for further reference. | + | |
| - | * You can set this Variable manually in the [[manual: | + | |
| - | * Once the `ENV_PATH` Variable | + | |
| - | * If your tool requires other environment variables to be set you can set them as well by creating an appropriate Keyboard Maestro variable with `ENV_` at the front. | + | |
| - | * For example, if you want to use [[https://www.perl.org/ | Perl]] with a custom library search path in a Execute Shell Script action, you can also create a Keyboard Maestro Variable `ENV_PERL5LIB` | + | |
| - | **Setting | + | If you need access to tools (executables) or files that you installed (not part of the system installation), |
| + | * Use an explicit, full path to the tool or file. See [[# | ||
| + | * Set the `$PATH` environment variable within each Execute Shell Script action. | ||
| + | * Set `ENV_PATH` Keyboard Maestro variable prior to the Execute Shell Script Action. | ||
| - | A shell script path that will work for many users is: | + | Any Keyboard Maestro variable |
| - | / | + | You can set this Variable manually in the [[manual:Preferences# |
| - | Of course, if you have tools or files you installed elsewhere, then you would need to include | + | If your tool requires other environment variables to be set you can set them as well by creating an appropriate Keyboard Maestro variable with `ENV_` at the front. |
| - | You can create the `ENV_PATH` Variable one time using the [[manual:Windows# | + | For example, if you want to use [[https:// |
| - | * Add a variable | + | |
| - | * Once set, it will remain unchanged until you change or delete it. | + | |
| - | {{:action: | + | (!) Note that if in the action |
| + | |||
| + | ===== Working Directory ===== | ||
| + | |||
| + | The working directory for any executed scripts will be set from the Keyboard Maestro `ENV_PWD` directory (v10.0+), or default to the root directory (`/`). | ||
| - | For a good discussion about this see: | ||
| - | * [KM can"t find shell commands ](https:// | ||
| - | * [[https:// | ||
| ===== Execute Script From Other Apps ===== | ===== Execute Script From Other Apps ===== | ||
| - | When you execute a shell script from other apps, like Terminal.app, | + | When you execute a shell script from other apps, like Terminal.app, |
| In order to access Keyboard Maestro Variables in these scripts, you must use a tool like [[https:// | In order to access Keyboard Maestro Variables in these scripts, you must use a tool like [[https:// | ||
| - | (!) Note that you do NOT need to replace spaces with underscores in your Variable name in this case, since you are ultimately using AppleScript in the Shell Script. | + | Here is a simple example to **get** a variable: |
| - | + | ||
| - | Here is a simple example | + | |
| - | < | + | |
| - | osascript -e 'tell application " | + | |
| - | </ | + | |
| - | + | ||
| - | If you are using Keyboard Maestro 7.1+ you can use the new simpler command | + | |
| < | < | ||
| osascript -e 'tell application " | osascript -e 'tell application " | ||
| </ | </ | ||
| - | To **set** a variable (and create if needed) | + | (!) Note that you do **not** replace spaces with underscores in your variable name in this case, since you are ultimately using AppleScript in the Shell Script. |
| + | |||
| + | To **set** a variable (and create if needed) you can use this: | ||
| < | < | ||
| osascript -e 'tell application " | osascript -e 'tell application " | ||
| Line 300: | Line 301: | ||
| === Actions === | === Actions === | ||
| + | * [[action: | ||
| * [[action: | * [[action: | ||
| * [[action: | * [[action: | ||
| Line 327: | Line 329: | ||
| - [[https:// | - [[https:// | ||
| - [[https:// | - [[https:// | ||
| + | For more info, see these discussions in the Keyboard Maestro Forum: | ||
| + | - [[https:// | ||
| + | - [[https:// | ||
| + | - [[https:// | ||
| + | - [[https:// | ||
| - [[https:// | - [[https:// | ||
| **Keywords: | **Keywords: | ||
action/Execute_a_Shell_Script.1574718820.txt.gz · Last modified: by JMichaelTX
