4

I always ran scripts using ./

For example ./script.sh

I recently learned that you can also type . script.sh

Is there any difference?

The second is much easier for me since my keyboard doesn't have a key for / but I need to press SHIFT -.

heemayl
  • 91,753

2 Answers2

8

When you do ./script.sh the script is run in a subshell. So any operation/change that the script is meant to do is taken place at the subshell, hence the parent shell i.e. from the shell the script was called from remains unaffected of the changes.

On the other hand, when you do . script.sh (. is the same as shell builtin source), the script is source meaning all the commands are executed in this instance of shell (from which it is called). Hence any changes in attributes such as variables, functions declaration affects the shell.

Normally source is used for user configuration files e.g. ~/.bashrc after making any modification to it e.g. adding a new path to PATH, so that the change is applied from the current shell session.

Perhaps an example will make you more clear :

$ cat script.sh  ##Our test script, containing just a variable (spam) declaration 
#!/bin/bash
spam=foobar

$ ./script.sh  ## Execute using ./script.sh

$ echo "$spam"  ## Prints nothing


$ . script.sh  ## Lets source it

$ echo "$spam"  ## Now we get it
foobar
heemayl
  • 91,753
  • 1
    . is not a shorthand for shell builtin source, that is the other way around : source, which came later, is a longhand for the builtin . – jlliagre Aug 14 '15 at 21:46
  • You might also add that if a sourced script exits, then the 'outer' shell (the one sourcing it) exits as well. So if script.sh in your example contained the statement exit, then invoking it with ./script.sh will (seem to) do nothing, whereas sourcing it from a terminal with . script.sh will have the surprising effect of making the terminal vanish. BTW, the exact same question has been asked and answered before. – zwets Aug 14 '15 at 22:40
1

Both execute the script that is located in the same directory that you are in, i.e. your current working directory.

Doing . script is referred to as sourcing the script in bash

From http://www.tldp.org/HOWTO/Bash-Prompt-HOWTO/x237.html

When a file is sourced (by typing either source filename or . filename at the command line), the lines of code in the file are executed as if they were printed at the command line. This is particularly useful with complex prompts, to allow them to be stored in files and called up by sourcing the file they are in.

In examples, you will find that I often include #!/bin/bash at the beginning of files including functions. This is not necessary if you are sourcing a file, just as it isn't necessary to chmod +x a file that is going to be sourced. I do this because it makes Vim (my editor of choice, no flames please - you use what you like) think I'm editing a shell script and turn on colour syntax highlighting.

There's a point to notice: the script is executed as if it was typed on the command line, meaning it expects bash syntax. Thus if you currently are working in bash and you want to execute a script that is written in tcsh style, bash will complain. By contrast if you do . bashstylescript.sh that will work.

Here's a demo of that. cwhile.sh is in tcsh style and whileloop.sh is in bash style.

 serg@ubuntu [/home/xieerqi]
================================
$ . cwhile.sh
bash: cwhile.sh: line 8: syntax error: unexpected end of file
 serg@ubuntu [/home/xieerqi]
================================
$ . whileloop.sh 
    28206 
    33672 
    18406 
    65344 
    12022 
    10751 
    29707 
    44303 
    15081 
    59236 

What about ./script ? In that case , the shell will read #! line, and run the appropriate shell to execute your script.

 serg@ubuntu [/home/xieerqi]
================================
$ ./cwhile.sh 
Welcome 1 times
Welcome 2 times
Welcome 3 times
Welcome 4 times
Welcome 5 times

As you can see, shell reads my #!/bin/tcsh line and lets tcsh execute the script.

Side-note : Doing . script.sh in other shells might not work, since it seems to be bash only thing. mksh for instance does not do that, but rather uses source script.sh way

Sergiy Kolodyazhnyy
  • 105,154
  • 20
  • 279
  • 497
  • That's the other way around, . script.sh is standard so should be supported by most shells (both bourne style and csh style) while source is originally a bashism. – jlliagre Aug 14 '15 at 21:52
  • So I guess mksh is just the odd one and doesn't support . Script.sh ? – Sergiy Kolodyazhnyy Aug 14 '15 at 21:59
  • mksh does actually support . script.sh – jlliagre Aug 14 '15 at 22:09
  • @jlliagre then why it doesn't work for me ? – Sergiy Kolodyazhnyy Aug 14 '15 at 22:21
  • I have no explanation but I guess some mistake in your test case. AFAIK, mksh has always supported the . builtin. Before it, pdksh already supported it too. Not doing it would have been a very serious bug. In any case, you haven't provided any evidence it doesn't work for you but if you can post a repeatable test case, that might deserve its own question. – jlliagre Aug 15 '15 at 00:05