The Differences Between Bash, Source, ".", and "./" Execution
This article explores various ways of running shell commands on Linux.
Join the DZone community and get the full member experience.Join For Free
While working on Linux, you probably run across some files that are not executing in the way you expected — for example, you might have a file in your current directory but it does not run when you enter its name. You get
file_name.sh command not found, but actually, the file is there. The file does not work, even having execution permission, because when you write something on the shell and run it, your
$PATH variable gets checked. If there is any command matching inside
$PATH directories, such as
/usr/bin, it will execute. Unless there is a matching command, you are going to get the error.
mkdir test && cd test echo 'echo "hello world PID:$$ ParentPID:$PPID"' > test.sh chmod 755 test.sh
After creating the script, let’s execute them in order.
test.sh #test.sh: command not found . test.sh #hello world PID:19245 ParentPID:19243 . ./test.sh # this is same with above. it is just specifies current directory explicitly. #hello world PID:19245 ParentPID:19243 ./test.sh #hello world PID:23044 ParentPID:19245 bash test.sh #hello world PID:23045 ParentPID:19245
Giving the file name directly does not work unless the current directory is in the
$PATH environment variable. While you are working on a POSIX standard shell such as ksh, the second command will also fail because while running a command shell check whether there is
/ inside the command or not. If there is, then it looks for the current working directory or absolute path you addressed. Opposite to this, then it looks at command inside
$PATH. The directory I am currently working on is not inside PATH, so it gets the error.
bash -posix test.sh #bash: test.sh: command not found . test.sh #bash: .: test.sh: file not found . ./test.sh #hello world PID:23493 ParentPID:19245 ./test.sh #hello world PID:23539 ParentPID:23493 bash test.sh #hello world PID:23540 ParentPID:23493 exit
Suppose you are using Bash. Running files by executing both
. file.sh or
. ./file.sh results will be the same, but not with
./test.sh. What about
If you use any shell command such as Bash or ksh, you will spawn a new shell to run the command. So every variable you have set is not available within the new shell. On the other hand,
source uses the current shell and does not spawn a new shell process. So any changes that you have made inside the file will affect your current shell. Above, as you can see by the outputs, PID changes when you execute by
bash since **they are spawning new processes. Above, as you can see, the Parent Process ID (PPID) of the
bash test.sh command is equal to the Process ID (PID) of
. ./test.sh command.
Let’s set a variable and print it inside
echo 'echo "STR is $STR"' >> test.sh STR="HELLO" bash test.sh #hello world PID:25035 ParentPID:19245 #STR is . test.sh #hello world PID:19245 ParentPID:19243 #STR is HELLO source test.sh #hello world PID:19245 ParentPID:19243 #STR is HELLO
bash test.sh command does not give
$STR variable output because the new shell does not know. It didn’t set inside the new shell. Let’s set a variable inside the script.
echo 'NEWSTR="WORLD"' >> test.sh echo 'echo "NEWSTR is $NEWSTR"' >> test.sh bash test.sh #hello world PID:25318 ParentPID:19245 #STR is #NEWSTR is WORLD echo $NEWSTR #this will give empty output # . test.sh #hello world PID:19245 ParentPID:19243 #STR is HELLO #NEWSTR is WORLD echo $NEWSTR # WORLD source test.sh #hello world PID:19245 ParentPID:19243 # STR is # NEWSTR is WORLD echo $NEWSTR # WORLD
source runs inside the current shell, thus we can see the new variable. That’s why running the
bash .bashrc command does not update your PATH variable. You should run with
source command or run with
.. Therefore, you must use source command to change the PATH variable.
Lastly, let's try this information to change and set the PATH variable.
mkdir directory && cd directory echo 'echo "FILE"' > file.sh && chmod 755 file.sh echo 'echo "COMMAND"' > echocommand && chmod 755 echocommand pwd # /home/ofk/test/directory cd # change PATH variable inside your .profile (or where ever you set PATH) file and add above path # PATH="$PATH:/home/ofk/test/directory" bash .profile # try to run echocommand or file.sh echocommand # echocommand: command not found file.sh # file.sh: command not found source .profile echocommand # COMMAND file.sh # FILE
shell commands (bash, ksh) start new shells and run commands.
. file_name or
source commands run on the current shell.
Opinions expressed by DZone contributors are their own.