What is the difference between executing a Bash script like A and sourcing a Bash script like B?
A
> ./myscript
B
> source myscript
Super User is a question and answer site for computer enthusiasts and power users. It only takes a minute to sign up.
Sign up to join this communityWhat is the difference between executing a Bash script like A and sourcing a Bash script like B?
A
> ./myscript
B
> source myscript
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:
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.
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.
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.
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.
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:
source myscript.sh
and . myscript.sh
?
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.
In addition to above,
executing the script as ./myscript
requires execute permission for file myscript while sourcing does not require any execute permission. That is why chmod +x myscript
is not required before source myscript
bash myscript
.
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.
Sourcing you get all the extra variables defined in the script.
So if you have configs or function definitions you should source and not execute. Executions are independent from the parents environment.
If I recall correct, executing the script runs the executable in the #!
line with the script file as an argument (typically starting a new shell and effectively sourcing the script into the new shell, as with #!/bin/sh
);
whereas, sourcing the script executes each line in your current shell environment, which is useful to mutate your current shell (for example, providing a way to define shell functions and export environment variables).
source
command executes the provided script (executable permission is not mandatory) in the current shell environment, while ./
executes the provided executable script in a new shell.
Also, check this answer for example: https://superuser.com/a/894748/432100
./
with both sourcing and executing. That only means 'Get the file from the current working directory', ensuring you are getting the specific file you are expecting and not something found in your path. I believe what you are referring to is . someScript.sh
(note the space between the period and the script) which is synonymous with source someScript.sh
(and for that matter with source ./someScript.sh
, although ./
isn't needed here because sourcing always expects a file. It's not searching the path for an executable.)
May 10 at 19:23