shell-script – Different Ways to Execute a Shell Script

executableshell-script

There are several ways to execute a script. The ones I know are:

/path/to/script # using the path (absolute or relative)
. script        # using the . (dot)
source script   # using the `source` command

Are there any other way? What are the differences between them? Are there situations that I must use one and not another?

Best Answer

Another way is by calling the interpreter and passing the path to the script to it:

/bin/sh /path/to/script

The dot and source are equivalent. (EDIT: no, they're not: as KeithB points out in a comment on another answer, "." only works in bash related shells, where "source" works in both bash and csh related shells.) It executes the script in-place (as if you copied and pasted the script right there). This means that any functions and non-local variables in the script remain. It also means if the script does a cd into a directory, you'll still be there when its done.

The other ways of running a script will run it in its own subshell. Variables in the script are not still alive when it's done. If the script changed directories, then it doesn't affect the calling environment.

/path/to/script and /bin/sh script are slightly different. Typically, a script has a "shebang" at the beginning that looks like this:

#! /bin/bash

This is the path to the script interpreter. If it specifies a different interpreter than you do when you execute it, then it may behave differently (or may not work at all).

For example, Perl scripts and Ruby scripts begin with (respectively):

#! /bin/perl

and

#! /bin/ruby

If you execute one of those scripts by running /bin/sh script, then they will not work at all.

Ubuntu actually doesn't use the bash shell, but a very similar one called dash. Scripts that require bash may work slightly wrong when called by doing /bin/sh script because you've just called a bash script using the dash interpreter.

Another small difference between calling the script directly and passing the script path to the interpreter is that the script must be marked executable to run it directly, but not to run it by passing the path to the interpreter.

Another minor variation: you can prefix any of these ways to execute a script with eval, so, you can have

eval sh script
eval script
eval . script

and so on. It doesn't actually change anything, but I thought I'd include it for thoroughness.

Related Question