./ vs . for running programs under terminal

I'd need some clarification regarding the way we run executables under the terminal. This might be a lame question but what is the difference between running an executable with ./an_executable and . an_executable (let's suppose that we are in the dir where an_executable is located)

I already know that the former makes the shell look for an_executable in the current directory (.), but why isn't a / needed after . when using the latter version?

Thanks in advance.


Solution 1:

The . executable syntax doesn't work with just any executable (or does it?). Instead, it's an alias for the bash source built-in. So the difference is mostly relevant to bash scripts, and the truth is that they're completely different things :)

./executable asks to run the executable "normally". ./ is a relative reference to the current path. This avoids having the shell (bash) try to locate the executable in a directory in its $PATH (which it would do if you didn't specify a path at all with the command). The reason why you can't just do executable is one of security; imagine you uncompress an archive you downloaded and it contains a malicious version of ls. If it ran directly from your current directory, you'd run that version without realizing.

On the other hand, . executable is saying "source a file named executable". Since you're directly naming the file and it really doesn't have to be an executable, the security restriction for the $PATH doesn't apply. Sourcing will only "run" (or seem to run) shell scripts. What it does is:

   source filename [arguments]
          Read and execute commands from filename  in  the  current  shell
          environment  and return the exit status of the last command exe‐
          cuted from filename.

So... What's really the difference between executing and sourcing? Assuming the same shell script, executing it (./script) will spawn a new shell, run the script inside that shell, and when the script exits, close that shell and return to the parent shell. In effect, it will start a new bash process to execute the script).

(. script) will cause the current shell to read the commands from the file as if they were being typed in the command line. There's no new shell spawned.

A very easy way to see how this behaves is to write a script that only contains exit. If you ./script it, nothing will seem to happen, this is because a new shell process is started, the exit command exits that new shell and your current shell is unaffected.

If you . script, you current terminal will close, because the exit command runs in the current shell. So it's equivalent to typing exit on the command prompt.