Команда «.» (точка) часто используется в шелл-скриптах, однако не все знают, что это синоним команды source, встроенной в оболочку bash. Обычно говорят, что она используется для включения (подключения, «инклудинга») неких внешних файлов внутри скрипта. Рассмотрим в чём заключается суть такого подключения на примере файла .bash_profile:
if [ -f ~/.bashrc ]; then
. ~/.bashrc
fi
На второй строчке с помощью оператора «.» выполняется содержимое файла ~/.bashrc . Может возникнуть вопрос, почему нельзя было для этого использовать, например, sh или просто сам bash.
Дело в том, что при использовании точки не создаётся копии bash-процесса — скрипт выполняется в текущем экземпляре bash, причём все переменные окружения, инициализированные в данном скрипте после его завершения не исчезают, а передаются в окружение системы. Вот в этом и состоит суть «включения». Наоборот, если скрипт запускается явным образом с помощью sh или bash, то создаётся локальная копия (форк) bash, и по завершении скрипта в родительский bash ничего не возвращается — все переменные окружения, созданные в скрипте безвозвратно теряются.
Проиллюстрируем сказанное на простом примере. Создадим файл script следующего содержания:
testenv="Hi there!";
echo "Внутренняя переменная testenv = $testenv";
Если теперь запустить скрипт с помощью sh, то на экран будет выведено значение внутренней переменной скрипта:
# sh script
# Внутренняя переменная testenv = Hi there!
Однако эта переменная не сохранится после завершения работы скрипта и не будет присутствовать в текущем окружении bash:
# echo $testenv;
#
Если же запустить скрипт точкой, то он выполнится с тем же результатом:
# . script
# Внутренняя переменная testenv = Hi there!
Только переменная testenv будет доступна среди переменных окружения текущей системной оболочки:
# echo $testenv;
# Hi there!
Дочерняя копия bash при использовании оператора точка создаётся только в том случае, когда процесс запускается в фоновом режиме. Это единственное исключение из общего правила.
В баше если написать, более понятно:
$ # Create a file testfile that contains a variable assignment:
$ echo «a=hello» > testfile
$ # Check that the variable expands to nothing:
$ echo «$a»
$ # Good. Now execute the file testfile with bash
$ bash testfile
$ # Check that the variable a still expands to nothing:
$ echo «$a»
$ # Now _source_ the file testfile:
$ . testfile
$ # Now check the value of the variable a:
$ echo «$a»
hello