How to determine function name from inside a function

BashFunction

Bash Problem Overview


If I have a Bash script like:

#!/bin/bash

f() {
  # echo function name, "f" in this case
}

Is there any way to do this? This could be used in help messages such as

printf "Usage: %s: blah blah blah \n" $(basename $0) >&2; 

Only in this case what I wanted is not $0, which is the file name of the script.

Bash Solutions


Solution 1 - Bash

You can use ${FUNCNAME[0]} in bash to get the function name.

Solution 2 - Bash

From the Bash Reference Manual: > FUNCNAME > > An array variable containing the names of all shell functions currently in the execution call stack. The element with index 0 is the name of any currently-executing shell function. The bottom-most element (the one with the highest index) is "main". This variable exists only when a shell function is executing. Assignments to FUNCNAME have no effect and return an error status. If FUNCNAME is unset, it loses its special properties, even if it is subsequently reset. > > This variable can be used with BASH_LINENO and BASH_SOURCE. Each element of FUNCNAME has corresponding elements in BASH_LINENO and BASH_SOURCE to describe the call stack. For instance, ${FUNCNAME[$i]} was called from the file ${BASH_SOURCE[$i+1]} at line number ${BASH_LINENO[$i]}. The caller builtin displays the current call stack using this information.

When bash arrays are accessed without an index the first element of the array will be returned, so $FUNCNAME will work in simple cases to provide the name of the immediately current function, but it also contains all other functions in the call stack. For example:

# in a file "foobar"
function foo {
    echo foo
    echo "In function $FUNCNAME: FUNCNAME=${FUNCNAME[*]}" >&2
}

function foobar {
    echo "$(foo)bar"
    echo "In function $FUNCNAME: FUNCNAME=${FUNCNAME[*]}" >&2
}

foobar

Will output:

$ bash foobar
In function foo: FUNCNAME=foo foobar main
foobar
In function foobar: FUNCNAME=foobar main

Solution 3 - Bash

I use ${FUNCNAME[0]} to print current function name

Solution 4 - Bash

The simplest way to get the function name (from inside a function) is dependent on which shell you are using:

Zsh version

someFunctionName() {
   echo $funcstack[1]
}

Bash version

someFunctionName() {
   echo ${FUNCNAME[0]}
}

Both

someFunctionName() {
  currentShell=$(ps -p $$ | awk "NR==2" | awk '{ print $4 }' | tr -d '-')
  if [[ $currentShell == 'bash' ]]; then
    echo ${FUNCNAME[0]}
  elif [[ $currentShell == 'zsh' ]]; then
    echo $funcstack[1]
  fi
}

A more robust version

columnX () {
    awk "{print \$$1}"
}
rowX () {
	awk "NR==$1"
}

checkShell() {
    ps -p $$ | columnX 4 | rowX 2 | tr -d - 
    # produces bash or zsh (or other shell name like fish)
}

showMethodName(){
    checkShell && echo ${FUNCNAME[0]} || echo $funcstack[1] 
}
showMethodName

Solution 5 - Bash

Another example:

# in a file "foobar"
foo() {
    echo "$FUNCNAME fuction begins"
}

foobar() {
    echo "$FUNCNAME fuction begins"
}

echo 'begin main'
foo
foobar
echo 'end main'

Will output:

begin main
foo fuction begins
foobar fuction begins
end main

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionYanView Question on Stackoverflow
Solution 1 - BashTheBonsaiView Answer on Stackoverflow
Solution 2 - BashbschlueterView Answer on Stackoverflow
Solution 3 - BashVerdigrassView Answer on Stackoverflow
Solution 4 - BashjasonleonhardView Answer on Stackoverflow
Solution 5 - BashMickey WhiteView Answer on Stackoverflow