How shell executes commands:
From bash manual:
If the name is neither a shell function nor a builtin, and contains no slashes, bash searches each element of the PATH for a directory containing an executable file by that name.
This means that functions and shell built-in commands take precedence first, and if there's none - it searches for the command in the list of directories that are specified in PATH
variable.
Why my 'test' command didn't work ?
What you encountered is test
command which is a built-in command compatible with original Bourne shell in bash
. This command is silent, and is used for simple logic, arithmetic evaluation, and string evaluation. It is used in logic and if statements:
bash-4.3$ test 1 -le 2 && echo "1 is less that or equal to 2"
1 is less that or equal to 2
bash-4.3$ if test 1 -le 2 ; then echo "1 is less than or equal to 2"; fi
1 is less than or equal to 2
Note that test
and [
exactly the same:
bash-4.3$ [ 1 -le 2 ] && echo "1 is less that or equal to 2"
1 is less that or equal to 2
bash-4.3$ if [ 1 -le 2 ] ; then echo "1 is less than or equal to 2"; fi
1 is less than or equal to 2
There's also /usr/bin/test
which is among the standard utilities, and exist for portability and compatibility. If there was no test
built-in in your shell, it would look through the PATH
variable, and if /usr/bin/
happened to be before your ~/bin
on the list - it would run /usr/bin/test
. Here's an example of that:
bash-4.3$ enable -n test
bash-4.3$ PATH="$HOME/bin/:$PATH" test
I am ~/bin/test
Using enable -n
command we turn off the built-in test
, and run test
temporarily with modified PATH
such my ~/bin
is first on the list. The shell looks at the list, and finds my shell script ~/bin/test
and ran it.
NOTE: please don't do this! The above example is for demonstration only ! This is not a good way to run your scripts and is not recommended. Use appropriate naming, never name your commands same as shell built-ins or existing utilities. You have been warned.
Why did test.sh work ?
What happened in your test.sh
case is that there's no built-in or functions called test.sh
and therefore shell searched every directory in PATH
list, until it found your test.sh
file and ran it. That's why it works.
Does this behavior relate to file extensions ?
No. This has nothing to do with file extensions and in fact for most files extension is irrelevant. Shell cares for location of what you type in command-prompt, if it's a built-in or function or alias, and if the file you mention has executable permissions set.
Additionally, it cares about appropriate #!
line (which is more formally known as interpreter directive), because if you have shell script written say for C-shell but it doesn't have appropriate #!
line at the top, and you try to run it with bash
- the shell will try to run it but it will break due to incompatible syntax.
More generally, Linux and Unix-like systems mostly care about magic numbers which are first several bytes in a file that identify the file type.
test
is already used by a different application, and that is what you are running. Seeman test
test
is the name of a bash shell builtin - which will be executed first regardless of where~/bin
occurs in yourPATH