I found which alias or which compgen etc returns nothing.
Both of those are shell builtins. which knows nothing of shell builtins: it simply searches a path for executables.
For a more reliable result, use type.
$ type compgen
compgen is a shell builtin
$ type alias
alias is a shell builtin
type has better knowledge of what executes because it is a shell builtin.
Why which is unreliable
which often gives the wrong answer. Observe:
$ type pwd
pwd is a shell builtin
$ which pwd
/bin/pwd
When you run pwd, without specifying an explicit path, the shell will execute its builtin, not the executable that which found.
Here are more examples of which giving the wrong answer:
$ type echo
echo is a shell builtin
$ which echo
/bin/echo
$ type [
[ is a shell builtin
$ which [
/usr/bin/[
Observe:
$ type /bin/echo
/bin/echo is /bin/echo
When you give an explicit path for echo, such as /bin/echo, then the shell would run that executable, not its builtin. type knows that also, as you can see above.
How which works internally
On debian-like systems, which is a simple shell script, The relevant part of which is:
for ELEMENT in $PATH; do
if [ -z "$ELEMENT" ]; then
ELEMENT=.
fi
if [ -f "$ELEMENT/$PROGRAM" ] && [ -x "$ELEMENT/$PROGRAM" ]; then
puts "$ELEMENT/$PROGRAM"
RET=0
[ "$ALLMATCHES" -eq 1 ] || break
fi
done
As you can see, it does a simple search along the PATH for an executable file of the name given.