How to understand Source command in Linux
Overview
Now as I’m on holiday and not in Singapore, I cannot use the server in the office. So I want to build a work environment similar to the server on my laptop. The common way is to use a shell script to set the environment and customized commands. Then using source
command to run the shell script. In this process, I found that the shell script is a good way to understand the source
command.
Script Content
At the beginning part of the shell script, I need to set the project folder path as an environment variable, PROJ_FOLDER
. Then I can use this variable to set the path of other folders. The different beginnings of the shell script written by me are shown below.
#!/bin/bash
# Set the environment variable PROJ_FOLDER
AES_FOLDER=$(dirname "$(dirname "$(realpath "$0")")")
export PROJ_FOLDER="$AES_FOLDER"
echo "PROJ_FOLDER set to $PROJ_FOLDER"
#!/bin/bash
# Set the environment variable PROJ_FOLDER
AES_FOLDER=$(dirname "$(dirname "$(realpath "$BASH_SOURCE")")")
export PROJ_FOLDER="$AES_FOLDER"
echo "PROJ_FOLDER set to $PROJ_FOLDER"
The script path is $PROJ_FOLDER/bin/setproj.sh
. The only difference between the two scripts is the way to get the path of the script. The first one use $0
and the second one use $BASH_SOURCE
. Then I get its grandparent folder by dirname
command. At last, I set the environment variable PROJ_FOLDER
to the grandparent folder path.
Result of Source Command
Now we use the source
command to run the shell script. Which one will set the PROJ_FOLDER
correctly? The result is shown below.
PROJ_FOLDER set to /mnt/hgfs
PROJ_FOLDER set to /mnt/hgfs/aes
The first one is the result of the first shell script. The second one is the result of the second shell script. I have to say the first result is wrong. The path it set is the parent folder of the expected PROJ_FOLDER
.
But wait, why the first one is wrong? The setproj.sh
is at the path PROJ_FOLDER/bin/setproj.sh
. After we use $0
to get its position, then we can use dirname
to get its parent folder, PROJ_FOLDER/bin
. Then we use dirname
again to get its grandfather folder, PROJ_FOLDER
. So the result should be correct. But why the result is wrong?
Explanation
So which path will the $0
get? Let’s use source
command to run the script as below.
#!/bin/bash
# Set the environment variable PROJ_FOLDER
AES_FOLDER=$(realpath "$0")
export PROJ_FOLDER="$AES_FOLDER"
echo "PROJ_FOLDER set to $PROJ_FOLDER"
The output is shown below.
PROJ_FOLDER set to /mnt/hgfs/aes/bash
Hence, now everything is clear. The output shows that the script is run in a subshell, /mnt/hgfs/aes/bash
. We can use the $BASH_SOURCE
to get the path of the running script. Then we can set the PROJ_FOLDER
correctly.
Though the first script is wrong, and took me some time to solve this problem, it is a good way to understand the source
command.