thiagowfx's avatar

¬ just serendipity 🍀 (not just serendipity)

bash: disable pipefail

• 248 words • 2 min • updated

⚠️ This post is over one year old. It may no longer be up to date or relevant. Opinions may have changed.

We often do set -euo pipefail in shell scripts1. It’s an overall good habit in defensive programming.

Nonetheless, sometimes the default behavior for pipefail is desired.

Recently we had an example involving pre-commit.com and mdsh, consider this README.md file:

md
`> files=$(grep -rl '/spec/sources/0/targetRevision' --include="*.yaml" apps/overlays | sort -d -u) && if [ -z "$files" ]; then echo "None"; else echo "$files" | sed -e 's/^/- /'; fi`

The intention is to find all .yaml files that match the given string within the apps/overlays directory.

The result is added to the README.md file with a git pre-commit hook, which runs mdsh underneath, proudly showcasing a glimpse of literate programming.

What happens when there are no matches, and grep returns with exit code 1?

`> files=$(grep -rl '/spec/sources/0/targetRevision' --include="*.yaml" apps/overlays | sort -d -u) && if [ -z "$files" ]; then echo "None"; else echo "$files" | sed -e 's/^/- /'; fi`

ERROR: some commands failed:

`> files=$(grep -rl '/spec/syncPolicy/automated' --include="*.yaml" apps/overlays | sort -d -u) && if [ -z "$files" ]; then echo "None"; else echo "$files" | sed -e 's/^/- /'; fi`
failed with exit status: 1.

Of course it fails, because mdsh sets -o pipefail.

The desired behavior is to disable it: set +o pipefail. Then it works properly:

> set +o pipefail && files=$(grep -rl '/spec/syncPolicy/automated' --include="*.yaml" apps/overlays | sort -d -u) && if [ -z "$files" ]; then echo "None"; else echo "$files" | sed -e 's/^/- /'; fi

  1. A gist with an explanation. ↩︎