Shell script¶
Directory layout¶
For builds that involve independent command-line tools, use Make, and follow DataMade’s Making Data Guidelines and Clark Grubb’s Makefile Style Guide. Examples: standard_profile_template
If a repository has scripts to set itself up and/or update itself, follow GitHub’s Scripts to Rule Them All. Examples: deploy, standard_profile_template
Filename conventions¶
bash
and sh
scripts should use the .sh
extension, unless they are in a script/
directory.
Shell options¶
Start a Bash script with set -euo pipefail. If the script explicitly handles unset variables, omit -u
. To see which command failed due to the -e
option, add -x
.
Reference: The Set Builtin
Code style¶
Check shell scripts using shellcheck.
Style shell scripts using shfmt: for example, shfmt -w -i 4 -sr (shfmt -f .)
.
Use:
[ ]
instead oftest
[ ]
instead of[[ ]]
, unless required$NAME
instead of${NAME}
, unless followed by a word characterSubshells to temporarily change directory, for example:
( cd subdir/ mv x.txt y.txt )
Instead of:
cd subdir/ mv x.txt y.txt cd .. # AVOID
Avoid:
set -x
in scripts run by continuous integration, because it will expand any secret variables
Continuous integration¶
Create a .github/workflows/shell.yml
file with:
name: Lint Shell
on: [push, pull_request]
jobs:
build:
if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name != github.repository
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: |
sudo apt update
sudo apt install shellcheck shfmt
- run: shellcheck $(shfmt -f .)
- run: shfmt -d -i 4 -sr $(shfmt -f .)
Reference¶
Shell Parameter Expansion (
##
,%%
, etc.)Conditional Constructs (
=
,=~
, etc.)