Get a List of Function Names in a Shell Script

Get a list of function names in a shell script

You can get a list of functions in your script by using the grep command on your own script. In order for this approach to work, you will need to structure your functions a certain way so grep can find them. Here is a sample:

$ cat my.sh
#!/bin/sh

function func1() # Short description
{
echo func1 parameters: $1 $2
}

function func2() # Short description
{
echo func2 parameters: $1 $2
}

function help() # Show a list of functions
{
grep "^function" $0
}

if [ "_$1" = "_" ]; then
help
else
"$@"
fi

Here is an interactive demo:

$ my.sh 
function func1() # Short description
function func2() # Short description
function help() # Show a list of functions


$ my.sh help
function func1() # Short description
function func2() # Short description
function help() # Show a list of functions


$ my.sh func1 a b
func1 parameters: a b

$ my.sh func2 x y
func2 parameters: x y

If you have "private" function that you don't want to show up in the help, then omit the "function" part:

my_private_function()
{
# Do something
}

How do I list the functions defined in my shell?

declare -F

Function names and definitions may be listed with the -f option to the
declare builtin command (see Bash Builtins). The -F option to declare
will list the function names only
(and optionally the source file and line number).

Bash Reference Manual

How would one get a list of functions in a shell script?

I assume bash is the shell.
typeset (or declare ) show the current environment, functions are part of the environment:

  • there's no inherent ordering in the environment (names are sorted on output)
  • the unwanted functions may be inherited from the environment, having been previously been
    marked for export with declare -x

You could experiment with "env" to start your script in a clean environment, try:

env -i "PATH=$PATH" "TERM=$TERM" "LANG=$LANG" myscript.sh

as starting point.

The best way to enumerate functions in bash is documented here: Where is function's declaration in bash?
Note that "declare -F" does not normalise the filename, it will be as invoked/sourced.

while read xx yy fn; do
func=( $(shopt -s extdebug; declare -F $fn) )
printf "%-30s %4i %-30s\n" "${func[@]:2}" "${func[1]}" "${func[0]}"
done < <(declare -F)

All you need to do is filter by the required filename, and sort by line number.

How to determine function name from inside a function

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

Loop through array of function names and execute all of them in a bash script

You get this error because you didn't quote your variables. Therefore test a is split into two parts.

Try it like this:

#!/bin/bash

functions_array=("test a" "test b" "testc")

test() {
echo "$1" # quoting here and ...
}

testc() { echo "testc!"; }

for i in "${functions_array[@]}"; do # also here
${i}
done

Listing defined functions in Bash

How about compgen:

compgen -A function   # compgen is a shell builtin

List bash functions and locations

The documentation does not clearly say that, but you need to call declare -F with a particular function as argument in order to obtain the file and line number of it's declaration. It can be done in a loop:

$ shopt -s extdebug
$ declare -F | while read foo bar fun ; do declare -F "$fun" ;done
$ shopt -u extdebug

How to get script name inside function in shell script?

As I commented, your scripts won't even do what you claimed it does:

this is unlikely. you did not show everything. in bash, functions are not exportable, therefore sourcing script2 in script1 won't make logger visible in script3. you must have done something in script3.

Indeed, copying your code and run it locally indicates what's happening:

$ ./script1.sh 
++ echo 'This is script1'
This is script1
++ source script2.sh
++ sh script3.sh
+ echo Script3 start
Script3 start
+ log
script3.sh: 3: script3.sh: log: not found
+ echo End of script3
End of script3
++ echo 'End of script1'
End of script1

notice the command not found error, which is exactly what I thought.


In fact, if you check bash's manual properly, there is a proper way of achieving what you want exactly:

BASH_SOURCE

An array variable whose members are the source filenames where the corresponding shell function names in the FUNCNAME array variable are defined. The shell function
${FUNCNAME[$i]} is defined in the file ${BASH_SOURCE[$i]} and called from ${BASH_SOURCE[$i+1]}.

read it carefully, it says function defined from ${BASH_SOURCE[$i]} and called from ${BASH_SOURCE[$i+1]}. In this case, logger resides in ${BASH_SOURCE[0]}, and the caller simply resides in ${BASH_SOURCE[1]}.

therefore, change your script2 to following shall work:

$ cat script2.sh 
log(){
echo "The calling script name is ${BASH_SOURCE[1]}"
}

(except I changed the function name so that it does not collide with my other shell tool.)


demo:

$ ./script1.sh 
This is script1
Script3 start
The calling script name is ./script3.sh
End of script3
End of script1

indeed does the work.

Finding main functions' names in a C file via Bash script

If I understand your specifications correctly this should do it:

root@local [~]# awk '/^[ \t]*(int|float|double)[ \t]+ksz_/ {print $2}' sample.txt

One thing I did not understand was whether there should only be one "_" after ksz so for example if "double ksz_Input_Helper1" is not something you want to match. In the regex above it does match.

I also chose to go with awk rather than grep as you said you want only the name the above awk prints only the second field using whitespace as a delimiter. If you still want to use grep this one does the same task:

root@local [~]# egrep '^\s*(int|float|double)\s+ksz_' sample.txt

Here is a breakdown(note in awk I use [ \t] in place of \s as I could not get it to recognize \s]:

^ - match start of line
\s* - match if there are 0 or more white spaces
(int|float|double) - match int, float, OR double
\s+ - match at least one whitespace
ksz_ - match literal string "ksz_"


Related Topics



Leave a reply



Submit