Как узнать каталог где находится скрипт (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) }
}

Если для других языков надо, додумаете сами :).


Комментарии

Оставить комментарий

Ответ на Как узнать каталог где находится скрипт (bash, perl, php)? Решение для symlink