Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Determine if a function exists in bash

People also ask

How do I delete a function in bash?

Form the unset entry in the bash manpage: If -f is specified, each name refers to a shell function, and the function definition is removed. Note: -f is only really necessary if a variable with the same name exists. If you do not also have a variable named foo , then unset foo will delete the function.

What is declare in bash?

'declare' is a bash built-in command that allows you to update attributes applied to variables within the scope of your shell. In addition, it can be used to declare a variable in longhand. Lastly, it allows you to peek into variables.

How does a function return a value in bash?

Bash function can return a string value by using a global variable. In the following example, a global variable, 'retval' is used. A string value is assigned and printed in this global variable before and after calling the function. The value of the global variable will be changed after calling the function.


Like this: [[ $(type -t foo) == function ]] && echo "Foo exists"

The built-in type command will tell you whether something is a function, built-in function, external command, or just not defined.

Additional examples:

$ LC_ALL=C type foo
bash: type: foo: not found

$ LC_ALL=C type ls
ls is aliased to `ls --color=auto'

$ which type

$ LC_ALL=C type type
type is a shell builtin

$ LC_ALL=C type -t rvm
function

$ if [ -n "$(LC_ALL=C type -t rvm)" ] && [ "$(LC_ALL=C type -t rvm)" = function ]; then echo rvm is a function; else echo rvm is NOT a function; fi
rvm is a function

The builtin bash command declare has an option -F that displays all defined function names. If given name arguments, it will display which of those functions are exist, and if all do it will set status accordingly:

$ fn_exists() { declare -F "$1" > /dev/null; }

$ unset f
$ fn_exists f && echo yes || echo no
no

$ f() { return; }
$ fn_exist f && echo yes || echo no
yes

If declare is 10x faster than test, this would seem the obvious answer.

Edit: Below, the -f option is superfluous with BASH, feel free to leave it out. Personally, I have trouble remembering which option does which, so I just use both. -f shows functions, and -F shows function names.

#!/bin/sh

function_exists() {
    declare -f -F $1 > /dev/null
    return $?
}

function_exists function_name && echo Exists || echo No such function

The "-F" option to declare causes it to only return the name of the found function, rather than the entire contents.

There shouldn't be any measurable performance penalty for using /dev/null, and if it worries you that much:

fname=`declare -f -F $1`
[ -n "$fname" ]    && echo Declare -f says $fname exists || echo Declare -f says $1 does not exist

Or combine the two, for your own pointless enjoyment. They both work.

fname=`declare -f -F $1`
errorlevel=$?
(( ! errorlevel )) && echo Errorlevel says $1 exists     || echo Errorlevel says $1 does not exist
[ -n "$fname" ]    && echo Declare -f says $fname exists || echo Declare -f says $1 does not exist

Borrowing from other solutions and comments, I came up with this:

fn_exists() {
  # appended double quote is an ugly trick to make sure we do get a string -- if $1 is not a known command, type does not output anything
  [ `type -t $1`"" == 'function' ]
}

Used as ...

if ! fn_exists $FN; then
    echo "Hey, $FN does not exist ! Duh."
    exit 2
fi

It checks if the given argument is a function, and avoids redirections and other grepping.


Dredging up an old post ... but I recently had use of this and tested both alternatives described with :

test_declare () {
    a () { echo 'a' ;}

    declare -f a > /dev/null
}

test_type () {
    a () { echo 'a' ;}
    type a | grep -q 'is a function'
}

echo 'declare'
time for i in $(seq 1 1000); do test_declare; done
echo 'type'
time for i in $(seq 1 100); do test_type; done

this generated :

real    0m0.064s
user    0m0.040s
sys     0m0.020s
type

real    0m2.769s
user    0m1.620s
sys     0m1.130s

declare is a helluvalot faster !