11

OK, so source runs the script in the current shell and . separately, as detailed in running script with ". " and with "source " for example, but, specifically, in my .bashrc file, I have:

[ -f ~/.bash_aliases ] && source ~/.bash_aliases
[ -f ~/.git-completion.bash ] && source ~/.git-completion.bash
[ -s ~/.autojump/etc/profile.d/autojump.sh ] && source ~/.autojump/etc/profile.d/autojump.sh

Can I replace this with:

[ -f ~/.bash_aliases ] && . ~/.bash_aliases
[ -f ~/.git-completion.bash ] && . ~/.git-completion.bash
[ -s ~/.autojump/etc/profile.d/autojump.sh ] && . ~/.autojump/etc/profile.d/autojump.sh

Will that work on OS X - is that the "POSIX" issue?

I tried it and the above still seem to work on Ubuntu (so they actually work with both source and ., that is, they give me the desired functionality in the shell). Should I choose one over the other, or am I missing something?

FWIW, on OS X, I source my .bashrc from my .bash_profile.

  • 1
    If it is 'sh' based shells I'd be using '.' for global compatibility and if you are using 'csh' based shells I'd be using source. – mdpc May 10 '14 at 20:40
  • 2
    Where in the linked post are you seeing that "source runs the script in the current shell and . separately"? They both run it in the current shell; otherwise there'd be no point – Michael Mrozek May 10 '14 at 21:01

2 Answers2

20

In bash, . and source are synonyms. Looking into bash source code, file builtin/source.def, you can see . and source use the same internal function source_builtin:

$BUILTIN source
$FUNCTION source_builtin
$SHORT_DOC source filename [arguments]
Execute commands from a file in the current shell.

Read and execute commands from FILENAME in the current shell.  The
entries in $PATH are used to find the directory containing FILENAME.
If any ARGUMENTS are supplied, they become the positional parameters
when FILENAME is executed.

Exit Status:
Returns the status of the last command executed in FILENAME; fails if
FILENAME cannot be read.
$END

$BUILTIN .
$DOCNAME dot
$FUNCTION source_builtin
$SHORT_DOC . filename [arguments]
Execute commands from a file in the current shell.

But source is not POSIX compatible, so if your script is called with POSIX /bin/sh, you should use . instead of source. Since POSIX doesn't restrict the shell, all your above script will work.

Personally, I always use . instead of source. (A lot of scripts that I wrote run under cron).

cuonglm
  • 153,898
  • All things being equal, use "source" instead of "." for one reason: try to search/grep for "." expressions in a large script. It's a nightmare. – abonet May 16 '14 at 20:44
  • Although this answer explains why using . is usually "better" than using source, as @abonet says, source is a lot easier to search for. Since periods are punctuation in many languages, it's easy for the eye to just skip over them. That's why I prefer to use source. – Joe May 16 '14 at 23:01
11

This is POSIX's definition of .dot:

The shell shall execute commands from the file in the current environment.

If file does not contain a /<slash>, the shell shall use the search path specified by $PATH to find the directory containing file. Unlike normal command search, however, the file searched for by the .dot utility need not be executable. If no readable file is found, a non-interactive shell shall abort; an interactive shell shall write a diagnostic message to standard error, but this condition shall not be considered a syntax error.

Considering the above, you might as well just replace your [ -f ./file ] && source ./file with . ./file altogether. If the file is not there the worst that will happen is you'll get a notice at login - which is probably information you'd want to have, I think.

Of course if you'd rather keep the test you could do:

test -f ./file && . $_
mikeserv
  • 58,310