Знайдіть абсолютний шлях від сценарію


10

У сценарії я потрапляю $0на можливий відносний шлях до нього. Для перетворення його в абсолютний я знайшов таке рішення, яке не розумію:

abspath=$(cd ${0%/*} && echo $PWD/${0##*/})

Моя проблема - магія всередині ${0%/*}та ${0##*/}. Схоже, колишній витягує dirname, а останній витягує ім'я файлу, я просто не розумію як.


2
Тут використовується розширення параметрів, але це не спрацювало для мене. Якщо ваш сценарій буде використовуватися тільки в Linux, ви можете використовувати readlink -f $0для отримання канонічного шляху.
Шон Дж. Гофф

1
@Shawn: 1 чудовий голос за коментарі, тому що ви ввели правильне мислення: "Для цього використовується розширення параметрів, але це не працює для мене". Тут dirnameкорисна програма.
D4RIO

mywiki.wooledge.org/BashFAQ/028 і cyberciti.biz/faq / ... каже BASH_SOURCEкраще $0, оскільки $0дає користувача набраний в команді, яка не може бути в даний час виконання скрипта.
Джоел Пурра,

Відповіді:


8

Визначення:

${string%substring} видаляє найкоротший збіг $substringз кінця $string.

${string##substring}видаляє найдовший збіг $substringз початку $string.

Ваш приклад:

abspath=$(cd ${0%/*} && echo $PWD/${0##*/})

${0%/*} видаляє все після останньої косої риски, даючи вам ім'я каталогів сценарію (що може бути відносним шляхом).

${0##*/} видаляє все до останньої косої риски, даючи вам лише назву сценарію.

Отже, ця команда змінюється до каталогу скрипту і об'єднує поточну робочу директорію (задану $PWD) і ім'ям сценарію, що дає вам абсолютний шлях.

Щоб побачити, що відбувається, спробуйте:

echo ${0%/*}
echo ${0##*/}

Додайте подвійні лапки навколо всіх змінних розширень, щоб впоратися з (майже всіма) іменами файлів, що містять спеціальні символи оболонки.
Жил 'ТАК - перестань бути злим'

10

Шон мав найпростіше рішення: readlink -f $0. Якщо ви хочете бути абсолютно впевненим, обробляти дивні імена файлів, ви можете скористатися цим:

absolute_path_x="$(readlink -fn -- "$0"; echo x)"
absolute_path="${absolute_path_x%x}"

Документація


1
Приємно бачити правильно оброблені остаточні рядки. На жаль readlink -fn, характерно для Linux, NetBSD та OpenBSD.
Жил 'ТАК - перестань бути злим'

4

Ось більш безпечний і зрозумілий спосіб виконати цю роботу:

abspath=$(unset CDPATH && cd "$(dirname "$0")" && echo $PWD/$(basename "$0"))

Примітки:

  • Якщо $0це оголене ім’я файлу без попереднього шляху, оригінальний скрипт вийде з ладу, але той, що вказаний тут, буде працювати. (Не проблема, $0але може бути в інших програмах.)
  • Будь-який підхід не вдасться, якщо шлях до файлу насправді не існує. (Не проблема $0, але може бути в інших програмах.)
  • unsetМає важливе значення , якщо ваш користувач може бути CDPATHвстановлений.
  • На відміну від readlink -fабо realpath, це буде працювати в нелінукс-версіях Unix (наприклад, Mac OS X).

2

Якщо ви хочете навчитися розширення параметрів оболонки, ви можете прочитати їх звідси , але розширення не завжди є найкращим вибором. У цьому випадку майже кожна система типу Unix має 2 хороших утиліти:

basename
dirname

Перший отримає ім'я файлу, а другий вилучить шлях, тому, якщо у вас є $ 0, скажіть:

dirname $0

І отримаєш шлях.

Ура


dirname може повернути відносні шляхи
opticyclic

0

Представляючи pwd, bash вбудований. Також знайдений в пакеті GNU coreutils.

$ sh ./cygdrive/c/cygwin/home/../../../../home/jaroslav/tmp/somewhere.sh
$0: ./cygdrive/c/cygwin/home/../../../../home/jaroslav/tmp/somewhere.sh
cheeky binary from /home/jaroslav/tmp (/home/jaroslav/tmp)

$ cat /home/jaroslav/tmp/somewhere.sh

abs=$( cd `dirname "$0"` ; pwd -P)
absBin=$( cd `dirname "$0"` ; /bin/pwd -P)
echo \$0: $0
echo cheeky binary from $abs \($absBin\)
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.