1. Overview
The ability to define functions is one of the most important features of Bash. Functions allow us to reuse code by calling and executing the same block many times in a script or a shell session.
When writing scripts in Bash or working in a shell, we may need to see what a function looks like to understand how it works or to modify it. In this tutorial, we’ll learn different ways to view the definition of a function in Bash.
2. View Function Definition via declare -f
One of the most common and straightforward ways to display the definition of a function in Bash is by using the declare command. We generally use declare to set variables and arrays in Bash. However, when used with the -f option, the declare command displays the definition of a function.
For example, let’s first assume we have a simple function named myfunc() defined within the script.sh script:
$ cat script.sh
#!/usr/bin/env bash
myfunc() {
echo 'A simple function'
}
First, we source the script so the function is available in the current shell:
$ . ./script.sh
Now, *to see the definition of myfunc(), we can use the declare -f command*:
$ declare -f myfunc
myfunc ()
{
echo 'A simple function'
}
This shows the function’s name and body.
3. View Function Definition via type
Another way to display the definition of a function is by using the type command. As expected, the type command in Bash displays the type of a command, including functions and their definitions.
To show the definition of the myfunc() function, we can use the type command after sourcing script.sh:
$ type myfunc
myfunc is a function
myfunc ()
{
echo 'A simple function'
}
The output is almost identical to that of declare -f except for the first line which explicitly states that myfunc() is a function.
We can remove the first line with the help of sed:
$ type myfunc | sed '1d'
myfunc ()
{
echo 'A simple function'
}
Now, we have solely the function definition shown as output.
4. View Function Definition via set
Another method for showing a function’s definition is via the set command. When used without arguments, set lists all available variables in the current shell session, including system and user-defined variables and functions.
Therefore, to list only the definition of the function we’re interested in, we can pipe the output of set into sed:
$ set | sed -n '/^myfunc ()/,/^}/p'
myfunc ()
{
echo 'A simple function'
}
Here, the sed command prints out the line beginning with myfunc () and all consecutive lines up until the line beginning with a curly brace, }, marking the end of the function. This works due to the automatic indentation of code.
We append p at the end of the sed instructions to indicate that it should print lines. The -n option is to suppress the default behavior of printing each line regardless of any match.
5. View Function Definition After trap
With the help of the trap command, we can set a trigger to print the function’s definition when a function is called.
Let’s first modify our function to include a trap and then source the script:
$ cat script.sh
#!/usr/bin/env bash
myfunc() {
trap 'declare -f ${FUNCNAME[0]}' RETURN
echo 'A simple function'
}
$ . ./script.sh
The RETURN signal will cause trap to trigger when the function ends. The trigger will execute declare -f ${FUNCNAME[0]} where the variable FUNCNAME[0] contains the name of the currently executing function:
$ myfunc
A simple function
myfunc ()
{
trap 'declare -f ${FUNCNAME[0]}' RETURN;
echo 'A simple function'
}
We see that the output of the function is returned normally, followed by the function’s definition.
6. Show the Location of a Function Definition
In addition to viewing a function’s definition, sometimes we may wish to show its location. We can accomplish this by setting extended debug options in Bash before calling the declare -F command.
6.1. Using the extdebug Shell Option
To show the name and location of a function definition in Bash, we can set the extdebug shell option and use the declare -F command:
$ shopt -s extdebug
$ declare -F myfunc
myfunc 2 ./script.sh
$ shopt -u extdebug
We use the shopt -s command to set a shell option. In this case, we set the extdebug option for extended shell debugging. With extdebug turned on, the -F flag of the declare command allows displaying the name of a function, followed by the line number where the function is defined and the path to the script or location where the function is defined. The last command above unsets the extended shell debugging option via -u.
Alternatively, we can write a custom function that executes these steps in a subshell instead:
$ find_function() ( shopt -s extdebug; declare -F "$@"; )
$ find_function myfunc
myfunc 2 ./script.sh
We can pass function names as arguments to our find_function() function, and it’ll return the same output as before. However, the advantage here is that each command runs in a spawned subshell instead of the current shell. Therefore, unsetting the extdebug option isn’t needed.
6.2. Using bash –debugger
Another approach to obtaining the location of a function definition is via the –debugger option of bash:
$ bash --debugger
$ . ./script.sh
$ declare -F myfunc
myfunc 2 ./script.sh
The bash –debugger command spawns a bash shell with extended debugging features. Afterward, we again source script.sh with the dot command to make myfunc() available. Finally, as before, declare -F will provide the function’s name and location.
7. Conclusion
In this article, we learned that Bash provides several ways to display the definition of a function. The most commonly used method is the declare -f command. Other useful methods are the type command, as well as the set command when used with sed. Furthermore, the trap command enables us to view a function’s definition at convenient times.
Finally, to see the location of a function’s definition, we can use the extended debugger option in Bash along with the declare -F command.