Sourcing vs Executing a script
If you're a Unix-like user and are not familiar with the difference between executing a script and sourcing it, then this article is for you.
Prerequisites: Basic familiarity with: Bash, Shell sessions, environment variables and processes.
The story began a few days ago when I got bored with my terminal prompt,
and I decided to customize it a bit. So I opened the
.bashrc
(equivalent of .zshrc
for Zsh users)
file and changed the PS1
variable to something more
suitable for my mood at that specific moment (yeah...being moody is not
easy). After saving the file and exiting, I noticed that the change was
not applied yet, which led to an interesting exploration that I
will share with you in this short article.
The content below applies to the
~/.bashrc
file if you're using bash, or~/.zshrc
for those using Zsh, like Mac users. As for Windows people, feel free to continue playing Solitaire :]
.bashrc file
You can think of the .bashrc
file as the one responsible
for the configuration of your shell, so whenever you open a new terminal
window, everything that is inside .bashrc
will be applied
to your shell session, whether it's environment variables, a customized
prompt, or anything you include in that file. The thing to note here is
that this file is read only in the beginning when a new shell process is
spawned on your system. So if you are already working in your terminal
window, and you make changes to these files, this will not be enough for
the changes to be applied. You will either have to open a new terminal
window, which will initiate a new shell session and read the
.bashrc
file, OR execute the .bashrc
file
using source
:
source ~/.bashrc
Which will immediately re-run the .bashrc
file and apply
the changes you made to your current shell.
What is this so[u]rcery?
If you run source --help
you will get the following:
Execute commands from a file in the current shell...
The key thing to note here is that executing a script with
./filename.sh
will run the file in a subshell, whereas
sourcing it will run it in the current shell session. For this to make
more sense, let's go through the following example one step at a time:
Create a file called test.sh
and add the following content:
#!/bin/bash
echo $testvar
Or #!/bin/zsh
if you're using Zsh.
Now exit Vim (yes, I assume you did not open vscode for two lines of code), make the file executable and add the following shell variable:
$ chmod +x ./test.sh
$ testvar=testing
This will add the testvar
variable to your current shell
session variables (which you can see by running set
). What
we need to pay attention to here is that this variable is ONLY available
for the current shell session.
Now, let's run the following:
$ ./test.sh
$
As you can see, nothing was printed! Why? well, running a script like
that will create a subshell with its own configurations and
variables, and this subshell has no access to the variables defined in
our initial shell, which is why it cannot find the
testvar
variable.
Now let's run the file again but using source
this time:
$ source ./test.sh
testing
$
Voila! This demonstrates the description initially provided:
Execute commands from a file in the current shell.
So now the script does have access to the testvar
variable
because it is running in the same shell session.
To sum up, we saw how using source
performs the following
main tasks:
- Run a file line by line, executing the commands as they are read.
- Execute the file in the current shell session instead of in a new one, allowing access to the existing environment variables and configurations.
Note: On some systems you can use a dot
.
instead ofsource
.Example:
. ~/.bashrc