In POSIX shells,
. is a special builtin, so its failure causes the shell to exit (in some shells like
bash, it's only done when in POSIX mode).
What qualifies as an error depends on the shell. Not all of them exit upon a syntax error when parsing the file, but most would exit when the sourced file can't be found or opened. I don't know of any that would exit if the last command in the sourced file returned with a non-zero exit status (unless the
errexit option is on of course).
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
Is a case where you want to source the file if it's there, and don't if it's not (or is empty here with
That is, it should not be considered an error (fatal error in POSIX shells) if the file is not there, that file is considered an optional file.
It would still be a (fatal) error if the file was not readable or was a directory or (in some shells) if there was a syntax error while parsing it which would be real error conditions that should be reported.
Some would argue that there's a race condition. But the only thing it means would be that the shell would exit with an error if the file is removed in between the
., but I'd argue it's valid to consider it an error that this fixed path file would suddenly vanish while the script is running.
On the other hand,
command . "$NVM_DIR/nvm.sh" 2> /dev/null
command¹ removes the special attribute to the
. command (so it doesn't exit the shell on error) would not work as:
- it would hide
.'s errors but also the errors of the commands run in the sourced file
- it would also hide real error conditions like the file having the wrong permissions.
Other common syntaxes (see for instance
grep -r /etc/default /etc/init* on Debian systems for the init scripts that haven't been converted to
systemd yet (where
EnvironmentFile=-/etc/default/service is used to specify an optional environment file instead)) include:
[ -e "$file" ] && . "$file"
Check the file it's there, still source it if it's empty. Still fatal error if it can't be opened (even though it's there, or was there). You may see more variants like
[ -f "$file" ] (exists and is a regular file),
[ -r "$file" ] (is readable), or combinations of those.
[ ! -e "$file" ] || . "$file"
A slightly better version. Makes it clearer that the file not existing is an OK case. That also means the
$? will reflect the exit status of the last command run in
$file (in the previous case, if you get
1, you don't know whether it's because
$file didn't exist or if that command failed).
command . "$file"
Expect the file to be there, but don't exit if it can't be interpreted.
[ ! -e "$file" ] || command . "$file"
Combination of the above: it's OK if the file is not there, and for POSIX shells, failures to open (or parse) the file are reported but are not fatal (which may be more desirable for
¹ Note: In
zsh however, you can't use
command like that unless in
sh emulation; note that in the Korn shell,
source is actually an alias for
command ., a non-special variant of