Есть ли способ для Sourced скрипт , чтобы узнать путь к себе? В основном я занимаюсь bash, хотя у меня есть коллеги, которые используют tcsh.
Я предполагаю, что мне может не повезти здесь, так как использование источников приводит к выполнению команд в текущей оболочке, так $0
что все равно остается вызов текущей оболочки, а не исходный сценарий. Моя лучшая мысль в настоящее время - сделать source $script $script
так, чтобы первый позиционный параметр содержал необходимую информацию. У кого-нибудь есть способ получше?
Чтобы было ясно, я поиске сценарий, не запустить его:
source foo.bash
Ответы:
In
tcsh
,$_
в начале сценария будет содержать местоположение, если файл был получен, и$0
содержит его, если он был запущен.В Баше:
источник
> tcsh --version\n tcsh 6.14.00 (Astron) 2005-03-25 (i486-intel-linux) options wide,nls,dl,al,kan,rh,nd,color,filec
, Если исходный файл не является интерактивным, исходный файл включается в родительский файл, как если бы он на самом деле являлся его частью (неразличимо), как вы упомянули в исходном вопросе. Я думаю, что ваш обходной путь позиционного параметра, вероятно, лучший подход. Тем не менее, обычный вопрос «почему вы хотите это сделать» и обычный ответ на этот вопрос «не делайте этого - делайте это вместо этого», где «это» часто нужно хранить ....
иsource
работали одинаково в этом отношении. Обратите внимание, что к нему$_
нужно обращаться в первом операторе файла, иначе он будет содержать последний аргумент предыдущей команды. Мне нравится включать shebang для моей собственной ссылки, чтобы я знал, для какой оболочки он предназначен, и для редактора, чтобы он использовал подсветку синтаксиса.source
, потом делаю.
. Я прошу прощения за некомпетентность. Они действительно идентичны. Во всяком случае,$BASH_SOURCE
работает.Я думаю, что вы могли бы использовать
$BASH_SOURCE
переменную. Возвращает путь, который был выполнен:Поэтому на следующем шаге мы должны проверить, является ли путь относительным или нет. Если это не относительно, все в порядке. Если это так, мы можем проверить путь
pwd
, объединить с/
и$BASH_SOURCE
.источник
source
поиск,$PATH
если данное имя не содержит/
. Порядок поиска зависит от параметров оболочки, подробности см. В руководстве.mydir="$(cd "$(dirname "$BASH_SOURCE")"; pwd)"
бы сработало?Для тщательности и ради поисковиков, вот что они делают ... Это вики сообщества, так что не стесняйтесь добавлять эквиваленты других оболочек (очевидно, $ BASH_SOURCE будет другим).
test.sh:
test2.sh:
Bash:
Тире
Zsh
источник
called=$_; echo $called; echo $_
? Разве этот отпечаток не будет$_
дважды?$_
специальному параметру: «При запуске оболочки задайте абсолютный путь, используемый для вызова оболочки или сценария оболочки, выполняемого в том виде, как он был передан в среде или списке аргументов. Затем расширяется до последнего аргумент предыдущей команды, после раскрытия. Также задайте полный путь, используемый для вызова каждой команды, выполненной и помещенной в среду, экспортируемую в эту команду. При проверке почты этот параметр содержит имя почтового файла. "#! /bin/sh
в том, что исходный файл имеет заголовок, что делает его бесполезным для источника. Это будет запускать новый экземпляр/bin/sh
, устанавливать переменные, а затем выходить из этого экземпляра, оставляя вызывающий экземпляр без изменений.#
в сценарии оболочки, является комментарием.#!
(Шебанг) имеет свое особое значение только в качестве первой строки исполняемого скрипта . В качестве первой строки файла, который получен, это просто комментарий.Это решение относится только к bash, а не к tcsh. Обратите внимание, что обычно предоставленный ответ
${BASH_SOURCE[0]}
не будет работать, если вы попытаетесь найти путь внутри функции.Я обнаружил, что эта строка всегда работает, независимо от того, используется ли файл в качестве сценария.
Если вы хотите следовать символическим ссылкам, используйте их
readlink
по пути, указанному выше, рекурсивно или не рекурсивно.Вот сценарий, чтобы попробовать его и сравнить с другими предлагаемыми решениями. Вызовите это как
source test1/test2/test_script.sh
илиbash test1/test2/test_script.sh
.Причина, по которой работает однострочник, объясняется использованием
BASH_SOURCE
переменной окружения и ее связанногоFUNCNAME
.[Источник: руководство Bash]
источник
Это работало для меня в bash, dash, ksh и zsh:
Выход для этих оболочек:
Я пытался заставить его работать для csh / tcsh, но это слишком сложно; Я придерживаюсь POSIX.
источник
Я был немного смущен ответом вики сообщества (от Шона Дж. Гоффа), поэтому я написал сценарий, чтобы разобраться. О
$_
, я нашел это: Использование_
в качестве переменной среды передается команде . Это переменная окружения, поэтому легко проверить ее значение неправильно.Ниже приведен сценарий, затем вывод. Они тоже в этом суть .
test-shell-default-variables.sh
Выход из
./test-shell-default-variables.sh {da,ba,z,k}sh
Что мы узнали?
$BASH_SOURCE
$BASH_SOURCE
работает в bash и только в bash.$0
том, когда текущий файл был получен другим файлом. В этом случае$BASH_PROFILE
содержит имя исходного файла, а не имя исходного файла.$0
$0
имеет то же значение, что и$BASH_SOURCE
в bash.$_
$_
оставлен нетронутым тире и кш.$_
затухает до последнего аргумента последнего вызова.$_
как «bash».$_
нетронутым. (при поиске это просто результат правила "последнего аргумента").Symlinks
КШ
ш
sh
, относительно этих тестов, они ведут себя как dash.источник
Для оболочки bash я нашел ответ @Dennis Williamson наиболее полезным, но в случае он не сработал
sudo
. Это делает:источник
Чтобы сделать ваш скрипт совместимым с bash и zsh вместо использования операторов if, вы можете просто написать
${BASH_SOURCE[0]:-${(%):-%x}}
. Результирующее значение будет взято с тогоBASH_SOURCE[0]
момента, когда оно определено, и${(%):-%x}}
когда BASH_SOURCE [0] не определено.источник
tl; dr
script=$(readlink -e -- "${BASH_SOURCE}")
(для bash очевидно)$BASH_SOURCE
контрольные примерыданный файл
/tmp/source1.sh
source
файл по-разномуsource
из/tmp
source
из/
source
из разных относительных путей/tmp/a
и/var
относительно
$0
во всех случаях, если в скрипт добавлена команда
тогда
source
скрипт всегда печатаетсяоднако , если скрипт был запущен , например,
тогда
$0
будет строковое значение/tmp/source1.sh
.источник
Этот ответ описывает, как
lsof
и немного магии grep - единственная вещь, которая, кажется, имеет шанс работать с вложенными исходными файлами в tcsh:источник
Может быть, это не будет работать с символическими ссылками или исходными файлами, но будет работать для обычных файлов. Принимается как ссылка сюда. @kenorb Нет имени, readlink, BASH_SOURCE.
источник
$0
дает вам информацию о текущем выполняемом скрипте, а не об источнике.На самом деле, «dirname $ 0» даст вам путь к сценарию, но вы должны немного его интерпретировать:
Вы должны подготовиться к обработке "." в качестве имени каталога при некоторых распространенных обстоятельствах. Я бы немного поэкспериментировал, так как я помню, что dirname встроено в ksh, и немного по-другому, когда "." появляется в PATH.
источник
$0
просто содержит «bash» для интерактивной оболочки, и это все, что видит сценарий.