61

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?

4 Answers 4

77

For 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 argument

So 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.

6
  • 3
    If the executable bit is not set, you can also run the script by doing ". ./script.sh" Jun 11, 2014 at 16:50
  • 2
    @Dog You are correct. The dot is a shortcut for built-in command 'source', which runs the script in the current bash process. So only the readable bit is required. Jun 11, 2014 at 18:35
  • 5
    @Dogeatcatworld while that is true, running . ./script.sh is not the same thing as bash script.sh (or ./script.sh. Consider the script #!/usr/bin/python -V<newline>print test.
    – casey
    Jun 11, 2014 at 21:49
  • 14
    Beware that sourcing a script could result in contamination of the interactive session. For example, should a script change the PATH environment variable, this change will affect commands run following the source. This approach should really be reserved for situations where you depend on the side effects (environment setup scripts and the like). For other situations where you can't change the permissions, running the command in the shebang line, following by the script name is the safest approach.
    – ctt
    Jun 12, 2014 at 0:15
  • 8
    Note that, if you source a script in the current directory, you don’t need to use ./; just say . 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
23

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.

4
  • 2
    Well, it makes no difference assuming that /bin/bash is the first bash in your $PATH.
    – cjm
    Jun 11, 2014 at 5:50
  • You're right. And the shebang #!/bin/bash is only working if there is a /bin/bash
    – xx4h
    Jun 11, 2014 at 5:52
  • Bash (version 4.2.37) on my system executes scripts even without the execution bit set. Why do you say execution bit is required? Jun 11, 2014 at 5:59
  • Yes, execution bit is only needed by invoking via ./script.sh.
    – xx4h
    Jun 11, 2014 at 6:04
16

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.
0
5

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

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .