Иногда нужно знать, в каком каталоге находится запущенный скрипт. Ну, например, в этом же каталоге лежат другие скрипты, которые должны быть запущены текущим выполняющемся скриптом. Для того, чтобы он их запустил, ему было бы неплохо знать, где их искать, потому что вы могли запустить скрипт находясь в совершенно произвольной директории, или воспользоваться для запуска не самим файлом скрипта, а символической ссылкой, лежащей в другом каталоге, которая указывает на файл скрипта.
Можно, конечно, поступить просто и в самом скрипте в переменной жёстко прописать полный путь до каталога, в котором этот скрипт лежит. Получится что-то вроде этого:
Для красивого решения проблемы нужно знать всего три вещи:
Можно, конечно, поступить просто и в самом скрипте в переменной жёстко прописать полный путь до каталога, в котором этот скрипт лежит. Получится что-то вроде этого:
#!/bin/bash DIRECTORY="/home/user/my_scripts" cd $DIRECTORY # запуск "соседних" скриптов ./script1.sh ./script2.shВполне рабочий вариант и две обозначенные выше проблемы будут решены, но если надо будет переместить скрипт в другой каталог, то и значение переменной придётся руками поменять в самом скрипте. Не очень удобно.
Для красивого решения проблемы нужно знать всего три вещи:
- Путь до выполняющегося скрипта можно узнать с помощью $0, но проблема в том, что он относительный, т.е. если вы запустите скрипт как ./script.sh, то и $0 будет содержать ./script.sh
- Команда readlink с параметром -e решит сразу две проблемы: во-первых она вернет полный путь до файла скрипта, если вы воспользовались для запуска символической ссылкой (даже если это была цепочка симлинков), а во-вторых преобразует относительный путь, если такой получен с помощью $0, в абсолютный
- Чтобы избавиться от имени файла скрипта в конце абсолютного пути, нужно воспользоваться командой dirname
#!/bin/bash # полный путь до скрипта ABSOLUTE_FILENAME=`readlink -e "$0"` # каталог в котором лежит скрипт DIRECTORY=`dirname "$ABSOLUTE_FILENAME"` # запуск "соседних" скриптов $DIRECTORY/script1.sh $DIRECTORY/script2.sh
А если не воспользовались для запуска символической ссылкой?
ОтветитьУдалитьДа и к чему городить огород.
Проще так:
DIRSCRIPT=$(pwd) # Текущая директория
echo "${DIRSCRIPT}"
Поправка.. Короче, разобрался. Все это туфта и то и другое.
УдалитьВот универсальное отличное решение, особенно, если учитывать, что во фряхе нет "readlink"..
DIRROOT=$(cd $(dirname $0) && pwd)
echo "${DIRROOT}"
И запускайте скрипт как хотите..
> А если не воспользовались для запуска символической ссылкой?
УдалитьОтработает всё совершенно корректно
А вы уверены, что называть туфтой решение в котором вы так и не разобрались хорошая идея?
> во фряхе нет "readlink"
Где я писал что это должно работать во фрибсд? Прочитайте название блога и сообщения.
Я не использую фрибсд, но позволю себе поинтересоваться, а какой интерпретатор команд вы используете в ней? На сколько мне известно, по умолчанию там tcsh или csh, а совсем не bash.
> И запускайте скрипт как хотите
Да что вы? Оукей. Тогда создайте символьную ссылку на свой скрипт в другом каталоге (не в том в котором лежит скрипт), войдите в этот каталог и выполните симлинк. Сильно удивитесь. Ваше решение вернет путь до каталога, в котором находится симлинк, вместо каталога в котором находится сам скрипт. Надеюсь доступно объяснил.
А еще поясните, пожалуйста, чем решение из двух команд, приведенное мной, "огороднее" вашего решения из трёх команд? Кроме того, переход в каталог для того что бы узнать путь до него немножко попахивает костылем, вам так не кажется? Но это я уже придираюсь, конечно, т. к. в баше без костылей никуда.
Успехов.
спасибо
ОтветитьУдалитьдля себя немного упростил
cd $(dirname $(readlink -e $0))
далее уже работаю с внутренней структурой
Пожалуйста! Разумно. Я написал в несколько шагов для того, чтобы было проще пояснить каждый из них в комментариях.
Удалитьhttp://stackoverflow.com/questions/59895/can-a-bash-script-tell-what-directory-its-stored-in и http://stackoverflow.com/questions/19313056/what-platform-independent-way-to-find-directory-of-shell-executable-in-shell-scr
УдалитьОгромное спасибо! Очень нужный скрипт, теперь пользую везде )
ОтветитьУдалитьСпасибо, очень полезно.
ОтветитьУдалитьОбычно использовал:
script_dir=$(dirname $0)
сd ${script_dir}/..
Но если пулять скрипт откуда-то из другого места, как это обычно и происходит, да еще и по ссылке, то нифига это не спасало. А предложенный вариант (упрощенный, как выше написал аноним) очень удобен и работает.
Еще раз спасибо!
Пожалуйста)
УдалитьНе работает.
ОтветитьУдалитьDebian 8 jessie stable
Скрипт лежит в папке /usr/local/etc/test/script.sh
Символьная ссылка находится в /usr/local/bin/script
Запускаю из домашней директории
Вывод
echo $0 # выведет "script"
echo $ABSOLUTE_FILENAME # выведет "."
echo $DIRECTORY # выведет ... ничего
ЧЯДНТ?
Работает.
Удалитьeqlbin:~ # cat /etc/test/script.sh
#!/bin/bash
ABSOLUTE_FILENAME=`readlink -e "$0"`
DIRECTORY=`dirname "$ABSOLUTE_FILENAME"`
echo ABSOLUTE_FILENAME=$ABSOLUTE_FILENAME
echo DIRECTORY: $DIRECTORY
eqlbin:~ # sh /usr/local/bin/script
ABSOLUTE_FILENAME=/etc/test/script.sh
DIRECTORY: /etc/test
ЧЯДНТ?
Какой вопрос - такой ответ
Спасибо! Ваша конструкция пригодилось при запуске скрипта по ссш на удаленной машине. По умолчанию директория была: ~. А она возвращает именно абсолютный путь к скрипту.
ОтветитьУдалитьПожалуйста! :)
Удалить