bash: disable pipefail
• 248 words • 2 min • updated
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:
`> 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