Как узнать каталог где находится скрипт (bash, perl, php)? Решение для symlink
Как в программе узнать из какого каталога её запустили? Существует несколько способов. Причем и для perl, и для bash, и для php. Раньше я без особого разбору пользовался тем какой первым вспомнил.
Но! Пришлось мне для одного программного продукта модифицировать структуру каталогов. Да все по хитрому! С кучей симлинков (symlink
)!
И что получилось? А получилось следующее. Если создать, например, такую структуру каталогов:
~/
prog/
bin/
etc/
log/
prog_1/
bin/ (симлинк на ~/prog/bin)
etc/
log/
prog_2/
bin/ (симлинк на ~/prog/bin)
etc/
log/
в ~/prog/bin положить скрипты. В каталогах ~/prog/etc, ~/prog_1/etc и ~/prog_2/etc должны находится конфигурационные файлы. В каталогах ~/prog/log, ~/prog_1/log и ~/prog_2/log – журналы работы скриптов. Если скрипты запущены из ~/prog_1/bin, то конфиги берутся из ~/prog_1/etc, а журналы пишутся в ~/prog_1/log. Если из ~/prog_2/bin, то используются ~/prog_2/etc и ~/prog_2/log соответственно.
Но тут начинается самое интересное. Все скрипты при запуске из ~/prog_1/bin и ~/prog_2/bin дружно взялись читать конфиги из ~/prog/etc и писать журналы в ~/prog/log!!!
В чём же дело? Оказалось что при использовании getcwd()
или __FILENAME__
выдается реальный путь к файлу, а не с учётом симлинка. Единственный способ узнать правильный путь – это смотреть переменную окружения PWD
.
Получилось так. Для bash:
P=$(dirname $0);
if [[ $P =~ ^/ ]]; then
P=$(dirname $0);
else
P=$(dirname $PWD$0);
fi;
Для php:
$PATH = dirname($argv[0]);
if (substr($PATH,0,1) != '/') { $PATH = dirname($_SERVER['PWD'].DIRECTORY_SEPARATOR.$argv[0]); }
Для perl:
BEGIN {
my $PATH = dirname($0);
if ($PATH !~ '^\/') { $PATH = dirname($ENV{PWD}."/".$0) }
}
Если для других языков надо, додумаете сами :).