If script.sh is just something typical like
#!/bin/bash
echo "Hello World!"
Is there a preferred way to run the script? I think you first have to chmod it so it becomes executable?
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. It only takes a minute to sign up.
Sign up to join this communityFor your specific script either way will work, except that ./script.sh
requires execution and readable bits, while bash script.sh
only requires readable bit.
The reason of the permissions requirement difference lies in how the program that interprets your script is loaded:
./script.sh
makes your shell run the file as if it was a regular executable.The shell forks itself and uses a system call (e.g. execve
) to make the operating system execute the file in the forked process. The operating system will check the file's permissions (hence the execution bit needs to be set) and forward the request to the program loader, which looks at the file and determines how to execute it. In Linux compiled executables start with an ELF magic number, while scripts start with a #!
(hashbang). A hashbang header means that the file is a script and needs to be interpreted by the program that is specified after the hashbang. This allows a script itself to tell the system how to interpret the script.
With your script, the program loader will execute /bin/bash
and pass ./script.sh
as the command-line argument.
bash script.sh
makes your shell run bash
and pass script.sh
as the command-line argumentSo the operating system will load bash
(not even looking at script.sh
, because it's just a command-line argument). The created bash
process will then interpret the script.sh
because it's passed as the command-line argument. Because script.sh
is only read by bash
as a regular file, the execution bit is not required.
I recommend using ./script.sh
though, because you might not know which interpreter the script is requiring. So let the program loader determine that for you.
. ./script.sh
is not the same thing as bash script.sh
(or ./script.sh
. Consider the script #!/usr/bin/python -V
<newline>print test
.
. script.sh
. But I agree with the people who discourage using the .
command on scripts that weren’t meant to be invoked that way. I’m surprised that nobody mentioned that, if the script contains exit
commands, and you source it, it could log you out. A less dire problem would be if the script does a cd
, as that would also affect the parent (interactive) shell.
Jun 12, 2014 at 0:43
bash script.sh
invokes the script directly using the bash.
./script.sh
is using the shebang #!/bin/bash
to determine how to execute.
If you really want to know, which binary is executed if you do a bash script.sh
you could find out with which bash
.
So in your example it makes no difference. Yes, you have to chmod +x script.sh
to be able to execute it directly via ./script.sh
.
/bin/bash
is the first bash
in your $PATH
.
#!/bin/bash
is only working if there is a /bin/bash
Create a file Delete_Self.sh like this:
#!/bin/rm
echo I am still here!
Run this script as sh Delete_Self.sh
you will see "I am still here!" echoed back.
Make it executable, and run it as ./Delete_Self.sh
you will see nothing is echoed back, while the file Delete_Self.sh
itself is gone.
So the difference is that:
bash script.sh
will ignore the #! line, because bash is specified as the program to run script.sh../script.sh
will read the #! line to determine the program to run script.sh
.In addition to the other answers, knowing the difference between running a script via ./script.sh
(i) and source ./script.sh
(ii) is useful - The (i) version creates a new shell in which to run the command, whereas (ii) runs it in the current shell - which can be mandatory if the executable changes environment variables that need to be preserved after the executable exits. For example, to activate a python conda environment the following must be used:
source activate my_env
N.B. Another alternative to source
that you may encounter is the .
builtin, i.e.
. activate my_env