Коли я пишу сценарій bash, як я можу отримати абсолютний шлях розташування поточного файлу?


16

Припустимо, у мене є файл bash під назвою myBash.bash. Він проживає в:

/myDirect/myFolder/myBash.bash

Тепер я хочу використовувати рядок /myDirect/myFolder(розташування myBash.bash) всередині сценарію. Чи є команда, яку я можу використати, щоб знайти це місце?

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


3
Це може бути краще підходить для потокового потоку. Перевірте ці питання: 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")")"- це найпростіший спосіб. Котирування всередині $()роботи як звичайні.
ДепресіяДаніель

@DepressDaniel Провели трохи досліджень в Інтернеті, ви маєте рацію: $()будучи передплатою, ви зможете мати котирування за межами. Я б не сказав, що це так просто, якщо тільки не усвідомити, що $()це всі підрозділи
Сергій Колодяжний,

5

якщо сценарій на вашому шляху, ви можете використовувати щось на кшталт

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

EDIT: після прочитання коментарів від Serg це може бути загальним рішенням, яке працює, чи буде сценарій на вашому шляху чи ні.

myloc==$(dirname "$(realpath $0)")
dirname "$myloc"

whichбільше підходить, коли скрипт знаходиться в одному з каталогів, що входять до PATHзмінної. Використовуйте $0всередині сценарію, як показує Zanna. Але ваша відповідь правильна, оскільки ви використовуєте dirnameзамість того, щоб возитися sed, отже, +1 для цього
Сергій Колодяжний

5

Прийнята відповідь здається ідеальною. Ось ще один спосіб зробити це:

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

/bin/pwdдрукує реальний шлях до каталогу, на відміну від pwdвбудованої команди.


0
wdir="$PWD"; [ "$PWD" = "/" ] && wdir=""
case "$0" in
  /*) scriptdir="${0}";;
  *) scriptdir="$wdir/${0#./}";;
esac
scriptdir="${scriptdir%/*}"
echo "$scriptdir"

Він береться за посилання від kenorb та andro.
Ні dirname, readlink, realpath, BASH_SOURCE
Усі вбудовані

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.