Consider the following script:
#!/bin/bash
hash ./a.sh  && echo ./a.sh exists
hash foo     && echo foo exists
hash bar/foo && echo bar/foo exists
bar/foo
It tries to check whether different commands exist, namely ./a.sh, foo and bar/foo (e.g. a foo executable inside bar directory). Afterwards, it tries to run bar/foo command. My output is:
./a.sh exists
./a.sh: line 3: hash: foo: not found
bar/foo exists
./a.sh: line 5: bar/foo: No such file or directory
First two lines are expected, as well as the last one. However, the third line says that hash command did not fail for bar/foo, which is strange.
I have though that using "hash" is preferrable for testing existence of commands which the script is about to use. At least, it's mentioned as a possible alternative in this SO answer. Turns out it does not work very well for commands which are relative paths (haven't tested with absolute paths). Why is that? type works better, but I considered them to be mostly synonymous.
 
     
    