5

What is the difference between these two commands?

. filename            # (A)

and

filename              # (B)

And how is this command related?

./filename            # (C)

Note: The # and the rest of the line after it are comments.

2

4 Answers 4

16

Command (A) is called sourcing the file which consists of shell commands. It may not be used for binary executables (see man file for information on how to determine a file's type). It causes the commands in the file to be executed in the current environment as if they were typed at the shell prompt. The results affect the current environment and so can do things like set the value of environment variables and change directories, adding function definitions, among other things. It is not necessary to set the execution bit using chmod. The file needs to be in the current directory or a full or relative path* must be included or the file can be in a location that's in the PATH environment variable (subject to whether the sourcepath option of shopt is set). It is not necessary to specify the current directory if that is where the file is located. These are all equivalent:

$ ls
filename
$ . filename
results

$ ls /some/directory/filename
/some/directory/filename
$ . /some/directory/filename
results

$ cd /elsewhere
$ echo $PATH
/some/directory
$ . filename
results

Command (B) causes the shell to execute the file only if the execution bit is on for the rights of the user (see man chmod). The file may be a shell script, a binary executable or another script such as Perl or Python (or written in a different shell). If there is no slash in the name (no directory is specified) then the file must be located in a directory that is included in the PATH environment variable. It is possible to include the current directory in the path, but I don't recommend it because it's a security risk. These are equivalent:

$ echo $PATH
/some/directory
$ filename
results

$ /some/directory/filename
results

Command (C) is essentially the same as command (B), but it specifies the current directory which is referred to as "." (just as the parent directory is referred to as "..". The PATH will not be searched to locate the file since a directory is specified.

[*] A relative path is one that does not start with a slash (/). It specifies a location relative to the current directory. "this/is/a/subdir" exists as a directory path under the current one as does "./this/is/a/subdir" (which specifies the same directory). "../another/set/of/dirs" is a set of directories below the parent of the current one.

5
  • Sourcing and running scripts are not equivalent because of the same-shell/subshell distinction. Jul 5, 2009 at 13:57
  • I didn't say they were equivalent. I said that the variations of sourcing are equivalent with each other and (separately) that the variations of running a script are equivalent to each other. Jul 5, 2009 at 14:15
  • @Dennis: It is possible to include the current directory in the path, but I don's recommend it because it's a security risk. --- Do you mean that the PATH ./bin/program.sh is a security risk for instance? Jul 5, 2009 at 14:40
  • 1
    No, I mean setting the PATH environment variable to include "." - in other words don't do this : PATH=.:$PATH it is safer, if you must do it, to do PATH=$PATH:. but I recommend using syntax like ./program.sh instead. BTW, your example, ./bin/program.sh, means "run program.sh from a directory called bin that is a subdirectory of the current directory". While that certainly can work, it is more likely that you would cd into the directory where the script exists and use ./program.sh Jul 5, 2009 at 14:58
  • 7
    Just say no to . in PATH Jul 5, 2009 at 15:58
7

If you source a script with

# . script

or

# source script

means that the script runs in the current shell.

If you run

# ./script

It will run in a new shell and will not have access to variables set in the current shell that have not been exported into the environment with "export".

1
2

Using the ". <executable>" runs the executable in the context of the running shell. If you set variables in the script, they will persist in shell that you source them from.

Normal behavior when you execute a program or script is to instantiate a new shell and launch the process. (That's why scripts start with #!/bin/sh, #!/bin/perl -w, etc -- that prescribes the shell and options to use)

"Sourcing" the script is useful for loading environment variables specific to an application, typically a database or development environment. If you run multiple Oracle or other database instances, you may have a set of "source" or "environment" scripts for the production, dev, and QA environments. If you have a compile farm that targets multiple platforms (ie. producing Solaris binaries from a Linux farm), you may have these scripts to easy load the proper environment variables.

1
0

A. . filename

Executes script file in current context. Mostly used to export variables from shell script to current running shell. So if export some new variable in "~/.bash_profile" file and we want to apply changes in current shell without logging off, we can use command

. ~/.bash_profile

to execute "~/.bash_profile" again in current context and get the new variables exported.

B. filename

If command is present in search path then it will get executed. File named command in current folder wont get executed, if current folder is not included in search path. To see current path use

echo $PATH

If executable named "filename" is present in more than one folder in path. The executable in first listed folder in path will be executed. To see where is the file that is getting executed when to type "filename" use

which filename

C. ./filename

It is used to execute filename named executable present in current working directory.

2
  • type -a filename is more informative than which (which doesn't know about shell builtins and aliases, for example). Jul 5, 2009 at 16:57
  • which(v2.19) is handling aliases well. It does not knows about shell built-ins. But if I do something like "type -a vi" where "vi" is aliased to "vim", then it does not shows me path of "vim" executable, instead it shows me path of "vi" executable. So both have their merits and demerits. Jul 5, 2009 at 17:36

You must log in to answer this question.

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