# shell-script-generator > Generate clean shell scripts following best practices. - Author: Tyler Garner - Repository: garnertb/ai - Version: 20260127122802 - Stars: 0 - Forks: 0 - Last Updated: 2026-02-07 - Source: https://github.com/garnertb/ai - Web: https://mule.run/skillshub/@@garnertb/ai~shell-script-generator:20260127122802 --- --- name: shell-script-generator description: Generate clean shell scripts following best practices. metadata: author: garnertb version: "1.1" --- # Shell Script Creator Generate shell scripts following best practices. ## Script Setup - Start scripts with shebang: (eg: `#!/bin/bash`) - Good idea to include `[[ "$TRACE" ]] && set -x` - `source` all dependencies before setting the `-e` or `+e` flags. - Include usage, description, and optional examples using `#/` comment prefix: ```bash #!/bin/bash #/ Usage: my-script [options] #/ #/ Brief description of the script's purpose. #/ #/ OPTIONS: #/ -h | --help Show this message. #/ -o An option. ``` - Scripts must accept both `-h` and `--help` arguments, print usage, and exit: ```bash if [ "$1" = "--help" ] || [ "$1" = "-h" ]; then grep '^#/' <"$0" | cut -c 4- exit 2 fi ``` ## Error Handling - Fail fast, use `set -eo pipefail` (or `set -o errexit`) to cause the script to exit when a command fails. - Use `|| true` on programs that you intentionally let exit non-zero. - Note that ignoring an exit status with `|| true` is not a good practice, though it can be used in test scripts, if necessary. - Set the exit code of a pipeline to that of the rightmost command that failed. - Disallow unset variables. - Usually use all three protections `set -o errexit -o nounset -o pipefail` - Use of `nounset` does require some extra code to either explicitly define variables (e.g. `FOO=`) or provide a default value, which may be blank: (e.g. `${FOO:-}`). - Avoid manually checking exit status with `$?`. ## Variables and Quoting - Always double quote variables, including subshells. No naked `$` signs. - Use Bash variable substitution if possible before awk/sed. - Generally use double quotes unless it makes more sense to use single quotes. - When expecting or exporting environment, consider namespacing variables when subshells may be involved. - Use lowercase for local/internal variables, uppercase for inherited/exported environment variables. - Use `${var}` for interpolation only when required (e.g., `${greeting}world`). - Use variables sparingly. Short paths and constants can be repeated for readability and easy search/replace. ## Conditionals and Control Flow - For simple conditionals, try using `&&` and `||`. - Put `then`, `do`, etc on same line, not newline. - Skip `[[ ... ]]` in your if-expression if you can test for exit code instead. - Use `test` or `[` for portable conditionals; use `[[` for advanced Bash features like glob matching. - Test for exit code vs output: ```bash # Test for exit code (-q mutes output) if grep -q 'foo' somefile; then ...; fi # Test for output (-m1 limits to one result) if [[ "$(grep -m1 'foo' somefile)" ]]; then ...; fi ``` - Prefer `$[x+y]` or `$((x+y))` for mathematical expressions. - Use `for` loops with `seq` or C-style syntax: ```bash for i in $(seq 0 9); do ...; done for ((n=0; n<10; n++)); do ...; done ``` ## Output and Formatting - Don't be afraid of `printf`, it's more powerful than `echo`. - Use hard tabs. Heredocs ignore leading tabs, allowing better indentation. - Use `<