Not all commands exist as separate executable files: some commands may be built-in to the shell you're using.
Apparently you don't have /usr/bin/which installed (although some package in your distribution might provide that).
Your type which outputs indicate that the which command in bash is actually an alias, and that alias is only defined when bash is invoked as an interactive shell. That means it's probably defined in /etc/bash.bashrc or ~/.bashrc, or in some script sourced from one of those.
When executing bash non-interactively (as in bash -c "type which" for example), then /etc/bash.bashrc and ~/.bashrc will be skipped, and so the alias won't get defined.
_which, in turn, might be a shell function. You could see its definition with type _which. Perhaps it is something similar to this:
which() {
IFS=:
for x in $PATH; do
if [ -x "$x/$1" ]; then
echo "$x/$1"
return 0
fi
done
echo "$1 not found in \$PATH"
return 1
}
So, if you want maximal portability for your script, it might be a good idea to use a function like that, and so let the script carry its own version of which within it.
whichis not installed but it works in zsh because it's a builtin. However, that does not explain thatwhich is aliased to `_which'after entering bash shell from zsh. – Arkadiusz Drabczyk Sep 21 '20 at 20:01