Как я могу получить абсолютное имя файла в сценарии оболочки в Mac OS X?


19

Я хотел бы получить абсолютное имя файла сценария, который в данный момент выполняется. Ссылки тоже должны быть разрешены.

В Linux это, кажется, делается так:

$(readlink -mn "$0")

но, readlinkпохоже, работает совсем по- другому на Mac OS X.

Я читал, что это делается с помощью

$(realpath $0)

в BSD, но это тоже не работает. Mac OS X не имеет realpath.

Любая идея?


1
Смотрите этот вопрос на SO: stackoverflow.com/questions/799679/…
Telemachus


Еще больше возможностей: stackoverflow.com/questions/7665/…
Герхард Бургер

Ответы:


19

Я обманываю и использую Perl для этой вещи:

#!/bin/bash
dirname=`perl -e 'use Cwd "abs_path";print abs_path(shift)' $0`
echo $dirname

Вы бы подумали, что я просто напишу весь скрипт на Perl, и часто я делаю, но не всегда.


Это работает, спасибо большое. Я дам вам голос, как только смогу. У кого-нибудь есть способ "чистой оболочки" сделать это?
Хуси

1
Боюсь, это так же хорошо, как и получается. (Учитывая множество многострочных хаков «чистой оболочки», которые можно найти в Google.)
Arjan

другая возможность (хотя и уродливая) - пройти путь «..», запоминая (через рекурсию или массив), пока «..» не вернет тот же файл, который вы только что имели (то есть: вы находитесь наверху), а затем вернитесь к сборке путь, как вы идете. Я видел, что ПО для резервного копирования Networker от Legato делает это во время strace как метод получения «истинного» пути (но, возможно, не абсолютного). Но это было бы намного больше кода, чем выше.
ericslaw

Не уверен, почему кто-то изменил код, чтобы использовать $ 1 вместо $ 0. Разве $ 1 не первый аргумент сценария bash? Я хотел путь к исполняемому скрипту bash, а не его первый аргумент.
ericslaw

27
#!/usr/bin/env bash
scriptDir="$(cd "$(dirname "$0")" && pwd -P)"

Работает в MacOSX тоже.
Алексар

1
Это супер! Есть много других слишком сложных ответов.
Джейсон С

3
Это работает только для файлов в каталоге с символическими ссылками, но не для файлов с символическими ссылками вообще
Герхард Бургер

1
Это также полезно unset -v CDPATHдо появления cd, поскольку cd может вызвать нежелательный вывод, если установлен CDPATH.
Binary

Чтобы справиться хотя бы с одним слоем символической ссылки на файл, вы также можете совместимым образом протестировать его с помощью readlink (у macs not -f): scriptDir=$(unset -v CDPATH; cd "$(dirname "$(readlink "$BASH_SOURCE" || echo "$BASH_SOURCE)")" && pwd -P)
Binary

0

Это обрабатывает комбинации символических ссылок и работает с файлами и папками:

#!/usr/bin/env bash
realpath()
{
    if ! pushd $1 &> /dev/null; then 
        pushd ${1##*/} &> /dev/null
        echo $( pwd -P )/${1%/*}
    else
        pwd -P
    fi
    popd > /dev/null
}

Но он не поддерживает realpath -relative-to. Это потребует преобразования, описанного здесь .


0

Другой подход:

# Install.
brew install coreutils

# Use the GNU variant.
grealpath --help
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.