= POSIX sh and shebangs :awk-1: link:../../../2020/12/15/shellcheck-repo.html :awk-2: link:../12/curl-awk-emails.html As I {awk-1}[keep moving] {awk-2}[towards POSIX], I'm on the process of migrating all my Bash scripts to POSIX sh. As I dropped `[[`, arrays and other Bashisms, I was left staring at the first line of every script, wondering what to do: what is the POSIX sh equivalent of `#!/usr/bin/env bash`? I already knew that POSIX says nothing about shebangs, and that the portable way to call a POSIX sh script is `sh script.sh`, but I didn't know what to do with that first line. What I had previously was: [source,shell] ---- #!/usr/bin/env bash set -Eeuo pipefail cd "$(dirname "${BASH_SOURCE[0]}")" ---- Obviously, the `$BASH_SOURCE` would be gone, and I would have to adapt some of my scripts to not rely on the script location. The `-E` and `-o pipefail` options were also gone, and would be replaced by nothing. I converted all of them to: [source,shell] ---- #!/bin/sh -eu ---- I moved the `-eu` options to the shebang line itself, striving for conciseness. But as I changed callers from `./script.sh` to `sh script.sh`, things started to fail. Some tests that should fail reported errors, but didn't return 1. My first reaction was to revert back to `./script.sh`, but the POSIX bug I caught is a strong strain, and when I went back to it, I figured that the callers were missing some flags. Specifically, `sh -eu script.sh`. Then it clicked: when running with `sh script.sh`, the shebang line with the sh options is ignored, as it is a comment! Which means that the shebang most friendly with POSIX is: [source,shell] ---- #!/bin/sh set -eu ---- . when running via `./script.sh`, if the system has an executable at `/bin/sh`, it will be used to run the script; . when running via `sh script.sh`, the sh options aren't ignored as previously. TIL.