0

I am using Big Sur for work. I want to write a bash script that uses some modern bash features.

The bash that comes with Big Sur is fairly old:

$ /bin/bash --version
GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin20)

So in I installed a later version with brew:

$ /usr/local/bin/bash --version
GNU bash, version 5.1.8(1)-release (x86_64-apple-darwin20.3.0)

This version has the features I want. However, I want the script to be cross-platform, so hardcoding this path at the beginning of scripts causes it not to work on our cloud environment, and certain other devs' machines:

#!/usr/local/bin/bash

From researching, I've found that a standard way to make a script cross-platform is to use this to get a bash location:

#!/usr/bin/env bash

Which lets the user define a location for bash. However, I have not been able to get the command working on my local environment!

This command returns nothing-- I'm expecting it should return the full path to a bash. It doesn't even return the path to the default system bash.

$ /usr/bin/env bash

I've added /usr/local/bin/bash to my .profile, but that hasn't seemed to work.

$ cat .profile 
export PATH="/usr/local/sbin:/usr/local/bin/bash:$PATH"

How do I configure my environment, shell, or whatever so that /usr/bin/env gives the path to /usr/local/bin/bash?

I'm using Big Sur 11.6.4 using Terminal 2.11.

1
  • 1
    If you want things to be cross-platform, it might be easier to adapt the shell bang during deployment/installation. This will have the positive side effect of avoiding surprises if env picks up the wrong bash (e.g. if a user redefined their PATH).
    – nohillside
    Commented Apr 4, 2022 at 15:42

2 Answers 2

3

I'm expecting it should return the full path to a bash

Your expectation is incorrect. /usr/bin/env bash launches a new interactive bash shell.

Demonstrating:

$ echo $$
14303
$ /usr/bin/env bash
$ echo $$
14339

Your PATH should contain the directory where bash is located.


Somewhat off-topic: if your bash script contains features that are not present in version 3.2 (for example, associative arrays), you can add an assertion to your code to abort early:

if (( BASH_VERSINFO[0] < 4 )); then
  echo "This code needs at least bash version 4" >&2
  exit 1
fi

Or suppose you need at least version 4.4:

if (( BASH_VERSINFO[0] * 10 + BASH_VERSINFO[1] < 44 )); then
  echo "This code needs at least bash version 4.4" >&2
  exit 1
fi
3
  • Playing around, I've discovered a more direct demonstration: $ /usr/bin/env bash --version GNU bash, version 5.1.8(1)-release (x86_64-apple-darwin20.3.0) Commented Apr 5, 2022 at 13:53
  • Yes, the BASH_VERSION variable contains "5.1.8(1)-release", but bash finds it easier to compare integers (extracted from the BASH_VERSINFO array) than version strings (need GNU sort's -V to do it reliably). Commented Apr 5, 2022 at 14:38
  • Er rather I meant as a demonstration that env was actually doing something, and in fact, finding the correct bash. For testing purposes and so on. Commented Apr 5, 2022 at 15:45
2

You need to look at some Unix tutorials to improve your knowledge of Unix. Any decnt one will explain how $PATH works and how to add to it.

The important thing to note here is that the elements of $PATH are directories not files. What /usr/bin/env does is it takes its first argument (bash in this case) and sees if it is in each directory in $PATH starting at the left. So to find and run /usr/local/bin/bash you need to have /usr/local/bin in your $PATH and that has to be before /bin which contains Apple's bash so the command you need in you ~/.profile (actually I think should be in ~/.bash_profile - even then read bash's documentation to see this is not the complete recommendation from bash's authors but everyone on the web seems to use this) is

export PATH="/usr/local/sbin:/usr/local/bin:$PATH"

Actually I would do more and use zsh as your shell as that is kept up to date by Apple and so you don't have to install extra software on your mac and it would be easier to run on your work colleges' machines.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .