Home » What is the difference between executing a Bash script vs sourcing it?

What is the difference between executing a Bash script vs sourcing it?

Solutons:


Both sourcing and executing the script will run the commands in the script line by line, as if you typed those commands by hand line by line.

The differences are:

  • When you execute the script you are opening a new shell, type the commands in the new shell, copy the output back to your current shell, then close the new shell. Any changes to environment will take effect only in the new shell and will be lost once the new shell is closed.
  • When you source the script you are typing the commands in your current shell. Any changes to the environment will take effect and stay in your current shell.

the “environment” are things like the current working directory and environment variables. also shell settings (among others history and completion features). there are more but those are the most visible.

Use source if you want the script to change the environment in your currently running shell. use execute otherwise.

If you want more details please read on.

Terminology

To clarify some common confusion about the syntax to execute and the syntax to source.

Syntax to execute:

./myscript

This will execute myscript provided that the file is executable and located in the current directory. The leading dot and slash (./) denotes the current directory. This is necessary because the current directory is usually not (and usually should not be) in $PATH.

myscript

This will execute myscript if the file is executable and located in some directory in $PATH.

Syntax to source:

source myscript

This will source myscript. The file need not be executable but it must be a valid shell script. The file can be in current directory or in a directory in $PATH.

. myscript

This will also source myscript. This “spelling” is the official one as defined by POSIX. Bash defined source as an alias to the dot.

and for completeness:

exec myscript

This will terminate the current shell and then execute myscript in place of the terminated shell. That means when myscript is done there no shell to return to. exec is powerful but rarely needed.

I put some links at the end for more information on these topics.

Demonstration

Consider myscript.sh with following content:

#!/bin/sh
# demonstrate setting a variable
echo "foo: "$(env | grep FOO)
export FOO=foo
echo "foo: "$(env | grep FOO)
# demonstrate changing of working directory
echo "PWD: "$PWD
cd somedir
echo "PWD: "$PWD

Before we execute the script first we check the current environment:

$ env | grep FOO
$ echo $PWD
/home/lesmana

The variable FOO is not defined and we are in the home directory.

Now we execute the file:

$ ./myscript.sh
foo:
foo: FOO=foo
PWD: /home/lesmana
PWD: /home/lesmana/somedir

Check the environment again:

$ env | grep FOO
$ echo $PWD
/home/lesmana

The variable FOO is not set and the working directory did not change.

The script output clearly shows that the variable was set and the directory was changed. The check afterwards show that the variable is not set and the directory not changed. What happened? The changes were made in a new shell.

The current shell spawned a new shell to run the script. The script is running in the new shell and all changes to the environment take effect in the new shell. After the script is done the new shell is destroyed. All changes to the environment in the new shell are destroyed with the new shell. Only the output text is printed in the current shell.

Now we source the file:

$ source myscript.sh
foo:
foo: FOO=foo
PWD: /home/lesmana
PWD: /home/lesmana/somedir

Check the environment again:

$ env | grep FOO
FOO=foo
$ echo $PWD
/home/lesmana/somedir

The variable FOO is set and the working directory has changed.

Sourcing the script does not create a new shell. All commands are run in the current shell and changes to the environment take effect in the current shell.

Note that in this simple example the output of executing is the same as sourcing the script. This is not necessarily always the case.

Another Demonstration

Consider following script pid.sh:

#!/bin/sh
echo $$

(the special variable $$ expands to the PID of the current running shell process)

First print the PID of the current shell:

$ echo $$
25009

Source the script:

$ source pid.sh
25009

Execute the script, note the PID:

$ ./pid.sh
25011

Source again:

$ source pid.sh
25009

Execute again:

$ ./pid.sh
25013

You can see that sourcing the script runs in the same process while executing the script creates a new process everytime. That new process is the new shell which was created for the execution of the script. Sourcing the script does not create a new shell and thus the PID stays the same.

Summary

Sourcing a script will run the commands in the current shell process. Changes to the environment take effect in the current shell.

Executing a script will run the commands in a new shell process. Changes to the environment take effect in the new shell and is lost when the script is done and the new shell is terminated.

Use source if you want the script to change the environment in your currently running shell. use execute otherwise.


See also:

  • https://stackoverflow.com/questions/6331075/why-do-you-need-dot-slash-before-script-name-to-run-it-in-bash
  • https://askubuntu.com/questions/182012/is-there-a-difference-between-and-source-in-bash-after-all
  • https://stackoverflow.com/questions/18351198/what-are-the-uses-of-the-exec-command-in-shell-scripts

Executing a script runs it in a separate child process, i.e., a separate instance of shell is invoked to process the script. This means that any environment variables etc., defined in the script can’t be updated in the parent (current) shell.

Sourcing a script means that it is parsed and executed by the current shell itself. It’s as if you typed the contents of the script. For this reason, the script being sourced need not be executable. But it has to be executable if you’re executing it of course.

If you have positional arguments in the current shell, they’re unchanged.

So if I have a file a.sh containing:

echo a $*

and I do:

$ set `date`
$ source ./a.sh

I get something like:

a Fri Dec 11 07:34:17 PST 2009

Whereas:

$ set `date`
$ ./a.sh

gives me:

a

Hope that helps.

sourcing is essentially the same as typing each line of the script in at the command prompt one at a time…

Execution starts a new process and then runs each line of the script, only modifying the current environment by what it returns.

Related Solutions

Extract file from docker image?

You can extract files from an image with the following commands: docker create $image # returns container ID docker cp $container_id:$source_path $destination_path docker rm $container_id According to the docker create documentation, this doesn't run the...

Transfer files using scp: permission denied

Your commands are trying to put the new Document to the root (/) of your machine. What you want to do is to transfer them to your home directory (since you have no permissions to write to /). If path to your home is something like /home/erez try the following:...

What’s the purpose of DH Parameters?

What exactly is the purpose of these DH Parameters? These parameters define how OpenSSL performs the Diffie-Hellman (DH) key-exchange. As you stated correctly they include a field prime p and a generator g. The purpose of the availability to customize these...

How to rsync multiple source folders

You can pass multiple source arguments. rsync -a /etc/fstab /home/user/download bkp This creates bkp/fstab and bkp/download, like the separate commands you gave. It may be desirable to preserve the source structure instead. To do this, use / as the source and...

Benefits of Structured Logging vs basic logging

There are two fundamental advances with the structured approach that can't be emulated using text logs without (sometimes extreme levels of) additional effort. Event Types When you write two events with log4net like: log.Debug("Disk quota {0} exceeded by user...

Interfaces vs Types in TypeScript

2019 Update The current answers and the official documentation are outdated. And for those new to TypeScript, the terminology used isn't clear without examples. Below is a list of up-to-date differences. 1. Objects / Functions Both can be used to describe the...

Get total as you type with added column (append) using jQuery

One issue if that the newly-added column id's are missing the id number. If you look at the id, it only shows "price-", when it should probably be "price-2-1", since the original ones are "price-1", and the original ones should probably be something like...

Determining if a file is a hard link or symbolic link?

Jim's answer explains how to test for a symlink: by using test's -L test. But testing for a "hard link" is, well, strictly speaking not what you want. Hard links work because of how Unix handles files: each file is represented by a single inode. Then a single...

How to restrict a Google search to results of a specific language?

You can do that using the advanced search options: http://www.googleguide.com/sharpening_queries.html I also found this, which might work for you: http://www.searchenginejournal.com/how-to-see-google-search-results-for-other-locations/25203/ Just wanted to add...

Random map generation

Among the many other related questions on the site, there's an often linked article for map generation: Polygonal Map Generation for Games you can glean some good strategies from that article, but it can't really be used as is. While not a tutorial, there's an...

How to prettyprint a JSON file?

The json module already implements some basic pretty printing in the dump and dumps functions, with the indent parameter that specifies how many spaces to indent by: >>> import json >>> >>> your_json = '["foo", {"bar":["baz", null,...

How can I avoid the battery charging when connected via USB?

I have an Android 4.0.3 phone without root access so can't test any of this but let me point you to /sys/class/power_supply/battery/ which gives some info/control over charging issues. In particular there is charging_enabled which gives the current state (0 not...

How to transform given dataset in python? [closed]

From your expected result, it appears that each "group" is based on contiguous id values. For this, you can use the compare-cumsum-groupby pattern, and then use agg to get the min and max values. # Sample data. df = pd.DataFrame( {'id': [1, 2, 2, 2, 2, 2, 1, 1,...

Output of the following C++ Program [closed]

It works exactly like this non-recursive translation: int func_0() { return 2; } int func_1() { return 3; } int func_2() { return func_1() + func_0(); } // Returns 3 + 2 = 5 int func_3() { return func_2() + func_1(); } // Returns 5 + 3 = 8 int func_4() { return...

Making a circle out of . (periods) [closed]

Here's the maths and even an example program in C: http://pixwiki.bafsoft.com/mags/5/articles/circle/sincos.htm (link no longer exists). And position: absolute, left and top will let you draw: http://www.w3.org/TR/CSS2/visuren.html#choose-position Any further...

Should I use a code converter (Python to C++)?

Generally it's an awful way to write code, and does not guarantee that it will be any faster. Things which are simple and fast in one language can be complex and slow in another. You're better off either learning how to write fast Python code or learning C++...

tkinter: cannot concatenate ‘str’ and ‘float’ objects

This one line is more than enough to cause the problem: text="რეგულარი >> "+2.23+ 'GEL' 2.23 is a floating-point value; 'GEL' is a string. What does it mean to add an arithmetic value and a string of letters? If you want the string label 'რეგულარი...