Old question, and in concrete it is not practically answerable to its full extend as we don't know the environment when the scripts gonna run. Therefore:
# early pipe for smoke testing required commands
hash test for false promises || exit 1
just line-up the important, non-standard commands you require very early in the script by their name only and if one is not found, hash will tell:
hash: no such command: for
hash: no such command: promises
Rationale: Exit the script early unsuccessfully before getting stuck in the middle wasting your precious time and potentially leaving a transaction on the system open in the middle and unfinished and instead direct the action back to the user that can control the runtime environment (fail-fast1).
This works well together with the accepted answer in the sense that you can use that answer for removing side-effects (and make the configuration by system-administrators autoritative) but likely even more with the remark from John Kugelman who commented afterwards to "Use plain commands and don't worry about $PATH
"2
Fail early, fail often, but always fail forward.
-- John C. Maxwell
- fail-fast, https://en.wikipedia.org/wiki/Fail-fast
-
I wish I had time to write a detailed answer. Cliff notes: Use plain commands and don't worry about $PATH
. Storing absolute command paths in variables is a common anti-pattern. $PATH
is under the user's control, so if it's not set right, that's their own fault. There's nothing they can exploit by changing it; they can always run a script's commands by hand, after all; or just edit the script and then run it. You only need to be careful with $PATH
if you elevate privileges. For instance, you'll see that su
and sudo
have protections to prevent exploits. [bold by me]
– John Kugelman; Nov 7, 2018 at 20:23