I love shell scripts because they’re so pragmatic and often allow me to get jobs done really quickly.

But sadly they’re full of pitfalls. Pitfalls everywhere you look.

Today, a coworker – who’s highly skilled, not a newbie by any means – ran into this:

$ bash -c 'set -u; foo=bar; if [[ "$foo" -eq "bar" ]]; then echo it matches; fi'
bash: line 1: bar: unbound variable

Why’s that happening? I know the answer. Do you? 😂

Stuff like that made me stop using shell scripts at work, unless they’re just 4 or 5 lines of absolutely trivial code. It’s now Python instead, even though the code is often much longer and clunkier, but at least people will understand it more easily and not trip over it when they make a tiny change.

⤋ Read More

@movq@www.uninformativ.de Variable names used with -eq in [[ ]] are automatically expanded even without $ as explained in the “ARITHMETIC EVALUATION” section of the bash man page. Interesting. Trying this on OpenBSD’s ksh, it seems “set -u” doesn’t affect that substitution.

⤋ Read More

@falsifian@www.falsifian.org Exactly! 🥳

So this works:

$ bash -c 'set -u; bar=1; foo=$bar; if [[ "foo" -eq "bar" ]]; then echo it matches; fi'
it matches

Without the misleading quotes:

$ bash -c 'set -u; bar=1; foo=$bar; if [[ foo -eq bar ]]; then echo it matches; fi'
it matches

As does this:

$ bash -c 'set -u; bar=1; foo=$bar; if (( foo == bar )); then echo it matches; fi'
it matches

What the person originally meant was what bender said:

$ bash -c 'set -u; foo=bar; if

⤋ Read More

@falsifian@www.falsifian.org Exactly! 🥳

So this works:

$ bash -c 'set -u; bar=1; foo=$bar; if [[ "foo" -eq "bar" ]]; then echo it matches; fi'
it matches

Without the misleading quotes:

$ bash -c 'set -u; bar=1; foo=$bar; if [[ foo -eq bar ]]; then echo it matches; fi'
it matches

As does this:

$ bash -c 'set -u; bar=1; foo=$bar; if (( foo == bar )); then echo it matches; fi'
it matches

What the person originally meant was what bender said:

$ bash -c 'set -u; foo=bar; if [[ "$foo" = "bar" ]]; then echo it matches; fi'
it matches

It’s all rather easy once you’ve understood it … but the initial error message of the initial version can be quite unexpected.

⤋ Read More

This one got me. I try to stick to POSIX sh so I’m not super familiar with the behavior of [[]]. I definitely should have gotten -eq, though.

⤋ Read More

Which once fixed, removing the extra [ and ] errors out with shellcheck as expected:

Invalid number for -eq. Use = to compare as string (or use $var to expand as a variable). [SC2170]

⤋ Read More

And errors out expectedly using dash or ash, very nice POSIX Sh compliant shells:

$ ./foo.sh
./foo.sh: line 5: [: bar: integer expression expected

So the lessons here are twofold:

  • Always use shellcheck to check your shell code
  • Never use Bash or rely on Bash(isms). Always prefer POSIX Sh

⤋ Read More

Participate

Login to join in on this yarn.