Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

Can anybody explain to me what the shell does in the two examples A) and B) below? It obviously behaves differently, but I can't find out why the output is different.

Example:
Let's have a script in our current directory named bla.sh with only one command:
echo ${0##/*} hello

A)
Started as: ./bla.sh
gives: ./bla.sh hello

B)
Started as: . bla.sh
gives: -bash hello

Since I use this in a script, the second output (because of the "-" in front of the -bash) kills the command. Of course, a simple -- before the ${...} helped, but I would love to understand what causes the output in the first place.
I love bash. And vi[m]. But I digress…

share|improve this question
add comment

3 Answers

up vote 18 down vote accepted

This command looks for an executable (either binary or script) named bla.sh in the current directory, then runs it as a normal program:

./bla.sh

It doesn't matter if bla.sh is a bash script, a perl or python one, or a compiled binary.


And this command calls the bash builtin command source (which has this confusing alias .), and reads the contents of bla.sh as if they were typed by you:

. bla.sh

The above is equivalent to:

source bla.sh

This of course only works when bla.sh contains commands for the bash shell (if that's the one you are currently using), it won't work for perl scripts or anything else.

(This is explained in help . and help source too.)


Usually it is best to use the ./bla.sh method. Only ~/.bashrc, ~/.profile and such files are usually sourced, because they are supposed to modify the current environment.

share|improve this answer
    
GREAT! Thanks a lot! –  Wolf Sep 13 '09 at 12:36
3  
Moreover, if you change bash environment in bla.sh, these changes are taken into account after . bla.sh but not after ./bla.sh. this is because . bla.sh runs in the context of the current bash whereas ./bla.sh runs as a subprocess. –  mouviciel Sep 15 '09 at 12:09
1  
See also mywiki.wooledge.org/BashFAQ/060 for some examples. Note that source is a bash alias for ., not the contrary and source won't work in other shells. –  mrucci Apr 15 '10 at 6:43
add comment

./<cmd> will execute the <cmd> program that resides in the current directory in a new (forked) process. It has to be executable. And also readable it starts with #!.

. <cmd> will make your current shell execute the shell script <cmd> that resides in your $PATH or the current directory in the current shell process. It has to be readable. It is an alias for the shell command source.

share|improve this answer
    
-1 . <cmd> will look for the program in $PATH and if it is not found THEN it will look in the current directory. –  dogbane Dec 21 '12 at 13:38
    
@dogbane Right, I corrected this. –  kmkaplan Dec 21 '12 at 13:41
    
FWIW, not all shells will search cwd for sourced sripts. zsh (at least with the config I have) requires . ./cmd –  bstpierre Dec 21 '12 at 13:55
1  
@bstpierre This seem to be a moving ground. The POSIX reference I have says that “the shell shall use the search path specified by PATH” and “Some older implementations searched the current directory for the file, even if the value of PATH disallowed it.” –  kmkaplan Dec 21 '12 at 14:02
add comment

./cmd uses explicit path (./ - current dir) to executable. And it is not necessary that it starts with #!.

. cmd - (aka source) - bash builtin command. One visible difference of executing through source is that it can set/modify environment variable of current shell.

share|improve this answer
    
more precisely, source is a bash-only alias to . (which is standard) –  grawity Dec 22 '12 at 12:25
    
You are right. Fixed. –  Leonid Volnitsky Dec 22 '12 at 13:20
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.