Как написать абсолютный путь к местоположению текущего файла при написании bash-скрипта?

16

Предположим, у меня есть файл bash myBash.bash. Он находится в:

/myDirect/myFolder/myBash.bash

Теперь я хочу использовать строку /myDirect/myFolder(местоположение myBash.bash) внутри скрипта. Есть ли команда, которую я могу использовать, чтобы найти это место?

Редактировать: Идея состоит в том, что я хочу создать zip-папку с кодом, который может быть запущен скриптом bash внутри этого zip-файла. Я знаю относительные пути к файлам кода внутри этого zip-файла, но не абсолютные пути, и они мне нужны. Одним из способов является жесткое кодирование пути или требование указания пути к файлу в качестве переменной. Однако мне было бы проще, если бы bash-файл мог сам определить, где он находится, а затем создать соответствующие пути к другому файлу из его знания структуры zip-файла.

dimpol
источник
3
Это может быть лучше подходит для stackoverflow. Проверьте эти вопросы: stackoverflow.com/questions/4774054/… stackoverflow.com/questions/59895/… .
Сетос II
1
использовать как.? уточните пожалуйста
Сергей Колодяжный
1
@SethosII этот вопрос полностью по теме здесь
Zanna
1
Я добавил больше контекста к вопросу. Я думал, что может быть простая / очевидная команда для получения пути к файлу исполняемого файла, но кажется, что ответ по крайней мере неочевиден.
Димпол
3
@Zanna Я не говорю, что это оффтоп, я думаю, что это просто более уместно и, как показано, ссылки уже задавались и отвечали там несколько раз.
Сетос II

Ответы:

24

Вы можете получить полный путь как:

realpath "$0"

И, как указал Сергей, вы можете использовать, dirnameчтобы убрать имя файла, как это

dirname "$(realpath $0)"

или даже лучше, чтобы предотвратить неуклюжие цитирование и расщепление слов со сложными именами файлов:

temp=$( realpath "$0"  ) && dirname "$temp"

Намного лучше, чем моя более ранняя идея, которая заключалась в том, чтобы разобрать ее (я знал, что будет лучший способ!)

realpath "$0" | sed 's|\(.*\)/.*|\1|'

Примечания

  • realpath возвращает фактический путь к файлу
  • $0 это файл (скрипт)
  • s|old|new|заменить oldнаnew
  • \(.*\)/сохранить любые символы раньше /на потом
  • \1 сохраненная часть
Занна
источник
2
+1 за использование $0и sedмагию. Но сказанное sedволшебство действительно не нужно, когда такие инструменты dirnameсуществуют
Сергей Колодяжный,
2
у вас уже есть ответ, используйте realpath: realpath "$( dirname $0 )"лично я бы использовал, readlinkно это я:readlink -e $(dirname $0)
Сергей Колодяжный
@Serg: не dirname "$(realpath "$0")"лучше? Обычно требуется знать родительский каталог ссылочного файла вместо родительского каталога символической ссылки, ссылающейся на указанный файл.
Дэвид Фёрстер
4
@Serg "$(dirname "$(realpath "$0")")"- самый простой способ. Кавычки внутри $()работают как обычно.
ДепрессияДаниэль
@DepressedDaniel Провел небольшое исследование в Интернете, вы правы: если вы недоработали, вы сможете $()получить кавычки снаружи. Я бы не сказал, что это так просто, если только не осознаешь $(), что все подшкуры
Сергей Колодяжный
5

если скрипт находится на вашем пути, вы можете использовать что-то вроде

$ myloc=$(dirname "$(which foo.sh)")
$ echo "$myloc"
/path/to/foo.sh

РЕДАКТИРОВАТЬ: после прочтения комментариев от Serg, это может быть универсальное решение, которое работает вне зависимости от того, находится скрипт в вашем пути или нет.

myloc==$(dirname "$(realpath $0)")
dirname "$myloc"
Антонелло Пьемонт
источник
whichбольше подходит для случаев, когда скрипт находится в одном из каталогов, которые являются частью PATHпеременной. Используйте $0из сценария, как показывает Занна. Но ваш ответ правильный, так как вы используете dirnameвместо того, чтобы возиться sed, поэтому +1 для этого
Сергей Колодяжный
5

Принятый ответ кажется идеальным. Вот еще один способ сделать это:

cd "$(dirname "$0")"
/bin/pwd

/bin/pwdпечатает реальный путь к каталогу, в отличие от pwdвстроенной команды.

Serv-вкл
источник
0
wdir="$PWD"; [ "$PWD" = "/" ] && wdir=""
case "$0" in
  /*) scriptdir="${0}";;
  *) scriptdir="$wdir/${0#./}";;
esac
scriptdir="${scriptdir%/*}"
echo "$scriptdir"

Он взят в качестве эталона из kenorb и андро
Нет, readlink имя папки, Realpath, BASH_SOURCE
Все это встроенные команды

HemanthJabalpuri
источник