Progrider

Programming discussion

Board index
Findings · Open discussion · shell

set -e doesn't do what you think in functions

Ran into this today and I'd have sworn I knew how it worked.

set -e f() { false; echo "still here"; } f || echo failed

That prints "still here". Because f is on the left of ||, errexit is turned off for everything inside it, however deep. It isn't something you can turn back on inside f. Same for if f; then, and for &&.

Also: local x=$(false) # exit status is local's, so 0

Assign on a separate line. And add set -o pipefail or the first half of a pipeline can fail and you won't hear about it.

5 replies

This is why I check every exit code by hand like an animal.

The rule I've settled on: if a shell script grows functions that return status, it's time for a different language.

And there's the other half of the thread. Every time.

I knew somebody would say that. It's 12 lines long!

Add a reply

Formatting help. Public, and removed when the thread expires.

Type name#secret for a tripcode, an identity others can't copy.

Posts and requests are logged for research. Privacy notice.