how to get the Unix shell executable name for a script marked as executable and bin/bash shebang

55 Views Asked by At

I use the function getTrueShellExeName() posted by mklement0 at https://stackoverflow.com/a/23011530/7471760 in order to get the shell name of a script.

This works perfectly well in most cases, but I have come to a situation involving executable scripts, where it fails (at least on Ubuntu 18).

Consider the following file testshell.sh:

#!/bin/bash

getTrueShellExeName() {
  local trueExe nextTarget 2>/dev/null # ignore error in shells without `local`
  # Determine the shell executable filename.
  trueExe=$(ps -o comm= $$) || return 1
  # Strip a leading "-", as added e.g. by OSX for login shells.
  [ "${trueExe#-}" = "$trueExe" ] || trueExe=${trueExe#-}
  # Determine full executable path.
  [ "${trueExe#/}" != "$trueExe" ] || trueExe=$([ -n "$ZSH_VERSION" ] && which -p "$trueExe" || which "$trueExe")
  # If the executable is a symlink, resolve it to its *ultimate*
  # target.
  while nextTarget=$(readlink "$trueExe"); do trueExe=$nextTarget; done
  # Output the executable name only.
  printf '%s\n' "$(basename "$trueExe")"
}

getTrueShellExeName

Make it executable via chmod +x testshell.sh

I observe the following behaviour in my terminal:

user@pc /tmp $ ./testshell.sh 

user@pc /tmp $ . testshell.sh 
bash
user@pc /tmp $ source testshell.sh 
bash
user@pc /tmp $ bash testshell.sh 
bash
user@pc /tmp $ dash testshell.sh 
dash
user@pc /tmp $ ksh testshell.sh 
ksh93
user@pc /tmp $ zsh testshell.sh 
zsh

So everything works fine except for the first line, where the script is executed.

Some remarks:

  • If I remove #!/bin/bash from the script, then ./testshell.sh prints bash as expected.
  • If I change #!/bin/bash in the script to #!/bin/bash -ex and run ./testshell.sh, it looks as if the script name is mistaken as the shell executable name:
+ getTrueShellExeName
+ local trueExe nextTarget
++ ps -o comm= 15096
+ trueExe=testshell.sh
+ '[' testshell.sh = testshell.sh ']'
+ '[' testshell.sh '!=' testshell.sh ']'
++ '[' -n '' ']'
++ which testshell.sh
+ trueExe=

Any idea how this can be solved to work in all cases, also when bin/bash is at the first line of the script, and it is executed rather than sourced?

0

There are 0 best solutions below