13

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.

ysap
  • 6,981
zipzap
  • 133

1 Answers1

22

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.

Fabby
  • 34,259
roadmr
  • 34,222
  • 9
  • 81
  • 93
  • Indeed, I was dealing with shell script when I noticed this behaviour. Thank you very much, thats the answer I needed. :) – zipzap Feb 12 '15 at 16:19
  • another question raised (if you don't mind):

    if my script contains just some simple messages with echo, and I am running it with ./script, then why am I able to see the messages in the parent shell if the subshell closes as soon as the execution ends?

    – zipzap Feb 12 '15 at 16:25
  • 2
    Because while the subshell is a separate process, it uses the same terminal as the invoking shell. It's similar to how you're still able to see ls output: you type the command, it runs, shows the output and then it ends, but the output remains in the terminal. – roadmr Feb 12 '15 at 17:47
  • 2
    Don't confuse shell with terminal; they're different things. Open a terminal, and the command prompt is given by a bash shell running inside it. If you type bash, you'll be running another shell; to the first shell, it's just a program to be run. If you type exit, you'll close the last shell you started but still be in the first shell (the one from when you started the terminal). Again, this all happens within the same terminal. – roadmr Feb 12 '15 at 17:58
  • It may be worth mentioning that . executable only works for shell scripts, but does nothing (or perhaps bad things) if executable is a compiled program or a script in a different language. – David Z Feb 12 '15 at 22:44
  • 1
    @DavidZ I did mention it :) "Sourcing will only "run" (or seem to run) shell scripts." – roadmr Feb 12 '15 at 22:59
  • Ah, yes, I missed that. It's kind of buried in the middle there. – David Z Feb 12 '15 at 23:01
  • The easiest way to see the difference is to set an environment variable in your script. It's impossible to affect the environment of a parent process, so a variable set in a script run with ./ won't be visible in the shell where you run it, while one set in one run with . will. E.g. echo export foo=bar >script;chmod +x script;./script; echo $foo vs. echo export foo=bar >script;. script; echo $foo--the former will print a blank line, while the latter will print bar. – Aaron Davies Feb 13 '15 at 06:41
  • Thanks! An upvote and an edit (though minor...) ;-) – Fabby Feb 17 '15 at 05:01