Determining which Interpreter Parses a Shell Script in macOS

D

The first line of a shell script – beginning #! – is called a shebang and typically determines which interpreter parses the script’s contents. This is not always the case and on occasion it may be helpful to know which interpreter is being used.

Paste the following at a command prompt to create a script that demonstrates this:

Dummy Content
cat << 'EOF' > "${HOME}/which-interpreter.sh"
#!/bin/bash
ps -p "$$" | tail -1 | awk '{print $4}'
EOF

 

 

This script simply displays the interpreter that parses it, but before running the script let’s look at what the line ps -p "$$" | tail -1 | awk '{print $4}' does.

The ps command with the -p flag outputs information about the process matching the process ID (PID). The $$ represents the PID of the script. The output of ps -p "$$" is:

 PID TTY           TIME CMD
3740 ttys000    0:00.01 /bin/bash /Users/steve/which-interpreter.sh

 

 

This output is piped to tail to remove the header:

3740 ttys000    0:00.01 /bin/bash /Users/steve/which-interpreter.sh

 

 

The CMD portion of the output shows the command that launched the script: /bin/bash and the parameter passed to it /Users/steve/which-interpreter.sh. Only the command is of interest so the output is piped to awk to print the fourth field:

/bin/bash

 

 

Make the script executable:

Dummy Content
chmod +x "${HOME}/which-interpreter.sh"

 

 

Now let’s run the script:

Dummy Content
"${HOME}/which-interpreter.sh"
/bin/bash

 

 

It doesn’t matter if the shell being used to run the script is a different version of bash or even another shell like zsh. The shebang will still be honoured and the script parsed by the /bin/bash interpreter unless another interpreter is explicitly used to execute the script at the command prompt.

Here are some examples:

NOTE: I have two bash interpeters on my system. The one shipped with macOS: /bin/bash and the one installed via Homebrew: /usr/local/bin/bash. The latter is a symbolic link to /usr/local/Cellar/bash/5.0.16/bin/bash.

Dummy Content
/usr/local/bin/bash "${HOME}/which-interpreter.sh"
/usr/local/bin/bash

 

 

Dummy Content
/bin/zsh "${HOME}/which-interpreter.sh"
/bin/zsh

 

 

Dummy Content
/usr/bin/env bash "${HOME}/which-interpreter.sh"
bash

 

 

This last example only shows that the script is being parsed by a bash interpeter, but not which one. It could be /bin/bash or /usr/local/bin/bash or another bash interpreter.

To see which interpreter is being used, overwrite the existing script to include the which command:

Dummy Content
cat << 'EOF' > "${HOME}/which-interpreter.sh"
#!/bin/bash
which $(ps -p "$$" | tail -1 | awk '{print $4}')
EOF

 

 

Now run the amended script:

Dummy Content
/usr/bin/env bash "${HOME}/which-interpreter.sh"
/usr/local/bin/bash

 

 

Using /usr/bin/env bash from the command prompt or as part of a shebang instructs the script to use a bash interpreter to parse its contents, but doesn’t explicitly state which one. That is determined by the user’s search path which is stored in the PATH environmental variable:

Dummy Content
echo $PATH
/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin

 

 

The script is parsed by the first instance of bash found in the search path. In my case this is /usr/local/bin/bash, not /bin/bash.

Overwrite the existing script changing the shebang to #!/usr/bin/env bash:

Dummy Content
cat << 'EOF' > "${HOME}/which-interpreter.sh"
#!/usr/bin/env bash
which $(ps -p "$$" | tail -1 | awk '{print $4}')
EOF

 

 

Run the amended script:

Dummy Content
"${HOME}/which-interpreter.sh"
/usr/local/bin/bash

 

 

Care should be taken when using launchd to execute scripts with this type of shebang as launchd has a default search path limited to /usr/bin:/bin:/usr/sbin:/sbin. Consequently, if this script were run by launchd it would be parsed by the only available bash interpeter in that search path: /bin/bash.

About the author

A native Brit exiled in Japan, Steve spends too much of his time struggling with the Japanese language, dreaming of fish & chips and writing the occasional blog post he hopes others will find helpful.

Add comment

Steve

Recent Comments

Recent Posts