How to determine function name from inside a function
BashFunctionBash 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