What is the difference between using `sh` and `source`?
When you call source
or .
(the one is an alias to the other. source
cmd not POSIX - kind of bashism), you load and execute a shell script into the current shell process. So you can
- read variables set in the sourced script,
- use functions defined within it.
- and even execute forks and/or subprocess if script do this.
When you call sh
, you initiate a fork (sub-process or child) that runs a new session of /bin/sh
(which is often a symbolic link to bash
). In this case, environment variables set by the sub-script would be dropped when the sub-script terminate.
Caution: sh
could be a symlink to another shell.
Practical sample
For example, if you want to change current working directory by a specific manner, you could not do
$ cat <<eof >myCd2Doc.sh
#!/bin/sh
cd /usr/share/doc
eof
$ chmod +x myCd2Doc.sh
This won't do what you expect:
$ cd /tmp
$ pwd
/tmp
$ ~/myCd2Doc.sh
$ pwd
/tmp
because current working dir is part of environment and myCd2Doc.sh
would run in a subshell.
But:
$ cat >myCd2Doc.source <<eof
# Shell source file
myCd2Doc() {
cd /usr/share/doc
}
eof
$ . myCd2Doc.source
$ cd /tmp
$ pwd
/tmp
$ myCd2Doc
$ pwd
/usr/share/doc
Have a look at mycd
function!! (With bash completion based on Associative Array).
Execution level $SHLVL
$ cd /tmp
printf %b '\43\41/bin/bash\necho This is level \44SHLVL.\n' >qlvl.sh
$ bash qlvl.sh
This is level 2.
$ source qlvl.sh
This is level 1.
Recursion (when a script run from itself)
$ cat <<eoqlvl2 >qlvl2.sh
#!/bin/bash
export startLevel recursionLimit=5
echo This is level $SHLVL started:${startLevel:=$SHLVL}.
(( SHLVL < recursionLimit )) && ./qlvl2.sh
eoqlvl2
$ chmod +x qlvl2.sh
$ ./qlvl2.sh
This is level 2 started:2.
This is level 3 started:2.
This is level 4 started:2.
This is level 5 started:2.
$ source qlv2.sh
This is level 1 started:1.
This is level 2 started:1.
This is level 3 started:1.
This is level 4 started:1.
This is level 5 started:1.
A little futher
$ sed '$a ps --sid $SID fw' qlvl.sh >qlvl3.sh
$ chmod +x qlvl3.sh
$ export SID
$ read SID < <(ps ho sid $$)
$ echo $SID $$
8983 8983
( Current PID ($$
== process Id) are same identifier than SID (session ID). It's not alway true.)
$ ./qlvl3.sh
This is level 2.
PID TTY STAT TIME COMMAND
8983 pts/10 Ss 0:00 /bin/bash
10266 pts/10 S+ 0:00 \_ /bin/bash ./qlvl3.sh
10267 pts/10 R+ 0:00 \_ ps --sid 8983 fw
$ . qlvl3.sh
This is level 1.
PID TTY STAT TIME COMMAND
8983 pts/10 Ss 0:00 /bin/bash
10428 pts/10 R+ 0:00 \_ ps --sid 8983 fw
Dot .
is an alias of source
. So the only difference between two command are slash
replaced by space
.
And a final test:
$ printf %b '\43\41/bin/bash\necho Ending this.\nsle' \
'ep 1;exit 0\n' >finalTest.sh
$ bash finalTest.sh
Ending this.
$ source finalTest.sh
Ending this.
... You may notice a different behaviour between the two syntaxes. ;-)
Defining a variable with or without export
export
makes the variable available to sub-processes.
That is,
export name=value
means that the variable name is available to any process you run from that shell process. If you want a process to make use of this variable, use export
, and run the process from that shell.
name=value
means the variable scope is restricted to the shell, and is not available to any other process. You would use this for (say) loop variables, temporary variables etc.
It's important to note that exporting a variable doesn't make it available to parent processes. That is, specifying and exporting a variable in a spawned process doesn't make it available in the process that launched it.
Using dot or source while calling another script - what is the difference?
There is no difference.
From the manual:
source
source filename
A synonym for . (see Bourne Shell Builtins).
What is the difference between source script.sh and ./script.sh?
source script.sh
runs the script within the current process, thus all variable assignments are preserved as variables even after the script finishes (and don't have to be explicitly export
'd).
./script.sh
just runs the script in a subprocess, and any variables which are assigned disappear after the script is done.
What does the 'export' command do?
export
in sh
and related shells (such as Bash), marks an environment variable to be exported to child-processes, so that the child inherits them.
export
is defined in POSIX:
The shell shall give the export attribute to the variables corresponding to the specified names, which shall cause them to be in the environment of subsequently executed commands. If the name of a variable is followed by = word, then the value of that variable shall be set to word.
What is the difference between $(()) and expr?
$(())
will almost certainly be within the shell that you are using.expr
may be an external call
Export command in Unix
The shell expanded the non-existent variable $TEST
into an empty string, and then ran the command export
with no arguments. When you do that, the shell lists the exported environment variables.
If you want to export an empty variable TEST, you should have written any of these:
export TEST
export TEST=
export TEST=''
export TEST=""
(and in this case, there are other ways to achieve the same effect, such as export TEST=$TEST
or, more or less sanely, export TEST="$TEST"
, but that is normally abbreviated to export TEST
.)
The detailed declare -x
notation in the output is designed to allow you to take write the output to a file, and then reload the environment with the .
(dot) or source
commands. Different shells present the output differently, and not necessarily reusably.
The set
command is similar (but more complex). It can be used to set shell options, to set the positional arguments ($1
, $2
, etc), but when run with no arguments it lists the set variables. Note that not every variable that is created is an exported environment variable.
Related Topics
Using Jq to Fetch Key Value from JSON Output
Linux Mint - Adding Environment Variables Permanently
Does The Bios Copy The 512-Byte Bootloader to 0X7C00
How to Output Return Code in Shell
Intellij Idea Under Linux, No Such File or Directory on Main Class
Rename Multiple Files While Keeping the Same Extension on Linux
What Are The Advantages Napi Before The Irq Coalesce
Is There a Limit on Number of Tcp/Ip Connections Between MAChines on Linux
Shared Library in Fortran, Minimal Example Does Not Work
Bash Script to Find The Frequency of Every Letter in a File
Gcc -Mpreferred-Stack-Boundary Option
Append The Time Stamp to a File Name in Ubuntu
Why Characters Received in Serial Connection Only After Pressing Enter