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 FreeWhile 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.
So you need to address the path to your file. Let’s create a simple Linux shell script and have execution permission on the script. The below examples are written in Bash Shell.
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 source
and bash
commands?
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 ./
or 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 test.sh
script.
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
Apparently, the 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
.
and 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
Conclusion
./
or 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.
Comments