What is the difference between `./example.sh` and `sh example.sh`
array_name=(value1 ... valuen)
This is how to initializes an array in bash
only. When you execute ./example.sh
, the shebang line #!/bin/bash
tells the system to use bash
to execute.
However, when you execute sh example.sh
, sh
is used to execute. In many Unix systems (like Linux), sh
is equivalent to bash
. It seems sh
is a different shell on your system.
Difference between ./ and sh in UNIX
sh file
executes a shell-script file in a new shell process.
. file
executes a shell-script file in the current shell process.
./file
will execute the file in the current directory. The file can be a binary executable, or it can start with a hashbang line (the first line of the file in form of #!....
, for example #!/usr/bin/ruby
in a file would signify the script needs to be executed as a Ruby file). The file needs to have the executable flag set.
For example, if you have the script test.sh
:
#!/bin/sh
TEST=present
and you execute it with sh test.sh
, you'd launch a new sh
(or rather bash
, most likely, as one is softlinked to the other in modern systems), then define a new variable inside it, then exit. A subsequent echo $TEST
prints an empty line - the variable is not set in the outer shell.
If you launch it using . test.sh
, you'd execute the script using the current shell. The result of echo $TEST
would print present
.
If you launch it using ./test.sh
, the first line #!/bin/sh
would be detected, then it would be exactly as if you wrote /bin/sh ./test.sh
, which in this case boils down to the first scenario. But if the hashbang line was, for example, #!/usr/bin/perl -w
, the file would have been executed with /usr/bin/perl -w ./test.sh
.
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. ;-)
Whats the difference between running a shell script as ./script.sh and sh script.sh
Running it as ./script.sh
will make the kernel read the first line (the shebang), and then invoke bash to interpret the script. Running it as sh script.sh
uses whatever shell your system defaults sh
to (on Ubuntu this is Dash, which is sh-compatible, but doesn't support some of the extra features of Bash).
You can fix it by invoking it as bash script.sh
, or if it's your machine you can change /bin/sh
to be bash and not whatever it is currently (usually just by symlinking it - rm /bin/sh && ln -s /bin/bash /bin/sh
). Or you can just use ./script.sh
instead if that's already working ;)
If your shell is indeed dash and you want to modify the script to be compatible, https://wiki.ubuntu.com/DashAsBinSh has a helpful guide to the differences. In your sample it looks like you'd just have to remove the function keyword.
Why does behavior of `./example` and `sh example` different? (`zsh: text file busy: ./example`)
When you do
$ ./example
you are trying to execute
"example" which is being written to. This is not allowed.
When you do
$ sh example
sh
is reading
"example", then execute what is read. This is fine.
Related Topics
Error: Ld.So: Object Ld_Preload Cannot Be Preloaded: Ignored
How to Recursively Copy a Directory into Another and Replace Only the Files That Have Not Changed
How to Exclude a Folder When Performing File Operations I.E. Cp, Mv, Rm and Chown etc. in Linux
Bash: Add String to the End of the File Without Line Break
Fastest Way to Tell If Two Files Have the Same Contents in Unix/Linux
What Are Stalled-Cycles-Frontend and Stalled-Cycles-Backend in 'Perf Stat' Result
How to Tell Whether I'm in a Screen
One Command to Create a Directory and File Inside It Linux Command
Why Does Zookeeper Not Use My Log4J.Properties File Log Directory
Swift on Os X Compiling for Linux
How to Reinstall the Latest Cmake Version
How to Tell What a Linux Process Is Waiting For
How to Sleep in the Linux Kernel Space
How to Make Sure the Numpy Blas Libraries Are Available as Dynamically-Loadable Libraries
How to Perform Grep Operation on All Files in a Directory
Tcp_Tw_Reuse VS Tcp_Tw_Recycle:Which to Use (Or Both)
Git: Can't Push (Unpacker Error) Related to Permission Issues