Determine if a function exists in bash
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.