hash
is for me the most portable:
if hash nvm 2>/dev/null; then echo exists; else echo does not exist; fi
Why it does not work? Let's see what you do:
command -v nvm
# prints nothing and exits with 1
$(command -v nvm)
# prints nothing and exits with 1
[ -x "$(command -v nvm)" ]
exit status of command is ignored. Only the string returned by the command matters. So it is executed like this:
[ -x "" ]
test command exits with status 1, as the file ""
is not an executable (such file does not exists).
! [ -x "" ]
then you negate the return status, so it returns 0, i.e. true
If you which to use command -v to check if a file exists, check for it's return status, not the string:
if command -v nvm 2>/dev/null; then echo exists; else echo does not exist; fi
But hash is a bit more portable, better stick to hash.