Учитывая абсолютный или относительный путь (в Unix-подобной системе), я хотел бы определить полный путь к цели после разрешения любых промежуточных символических ссылок. Бонусные баллы за одновременное разрешение ~ имени пользователя.
Если целью является каталог, возможно, можно выполнить chdir () в каталог, а затем вызвать getcwd (), но я действительно хочу сделать это из сценария оболочки, а не писать помощник по Си. К сожалению, оболочки имеют тенденцию пытаться скрыть существование символических ссылок от пользователя (это bash на OS X):
$ ls -ld foo bar
drwxr-xr-x 2 greg greg 68 Aug 11 22:36 bar
lrwxr-xr-x 1 greg greg 3 Aug 11 22:36 foo -> bar
$ cd foo
$ pwd
/Users/greg/tmp/foo
$
То, что я хочу, это функция resol (), чтобы при выполнении из каталога tmp в приведенном выше примере, resol ("foo") == "/ Users / greg / tmp / bar".
cd
сначала до звонкаpwd -P
. Другими словами: это не позволит вам разрешить (см. Цель) символические ссылки на файлы или поврежденные символические ссылки, а для разрешения символических ссылок существующего каталога вам придется проделать дополнительную работу (восстановить предыдущий рабочий каталог или локализовать вызовыcd
andpwd -P
в скорлупе).Примечание редактора: вышеописанное работает с GNU
readlink
и FreeBSD / PC-BSD / OpenBSDreadlink
, но не на OS X с 10.11.GNU
readlink
предлагает дополнительные связанные параметры, например,-m
для разрешения символической ссылки, независимо от того, существует ли конечная цель.Обратите внимание, что начиная с GNU coreutils 8.15 (2012-01-06), существует программа realpath, которая менее тупая и более гибкая, чем описанная выше. Он также совместим с утилитой FreeBSD с тем же именем. Он также включает в себя функциональность для генерации относительного пути между двумя файлами.
[Добавление администратора ниже из комментария от halloleo - danorton]
Для Mac OS X (не менее 10.11.x) используйте
readlink
без-f
опции:Примечание редактора: это не приведет к рекурсивному разрешению символических ссылок и, следовательно, не сообщит о конечной цели; например, данная символическая ссылка, на
a
которую указывает ссылкаb
, которая, в свою очередь, указываетc
, что это будет только отчетb
(и не будет гарантировать, что он выводится как абсолютный путь ).Используйте следующую
perl
команду в OS X, чтобы заполнить пробел отсутствующейreadlink -f
функциональности:perl -MCwd -le 'print Cwd::abs_path(shift)' "$path"
источник
readlink
работает на OSX, но нуждается в другой синтаксис:readlink $path
без-f
.«pwd -P», кажется, работает, если вы просто хотите каталог, но если по какой-то причине вы хотите имя реального исполняемого файла, я не думаю, что это помогает. Вот мое решение:
источник
Один из моих любимых
realpath foo
источник
realpath
на Centos 6 с GNU coreutils 8.4.31. Я сталкивался с несколькими другими в Unix и Linux , у которых GNU coreutils упакован безrealpath
. Так что, похоже, это зависит не только от версии.realpath
более ,readlink
поскольку он предлагает опции , такие как флаги--relative-to
кажется, что именно то, что вы просите - он принимает произвольный путь, разрешает все символические ссылки и возвращает «реальный» путь - и это «стандартный * nix», который, вероятно, уже есть во всех системах
источник
По-другому:
источник
Собирая вместе некоторые из приведенных решений, зная, что readlink доступна в большинстве систем, но требует разных аргументов, это хорошо работает для меня в OSX и Debian. Я не уверен насчет систем BSD. Возможно условие должно быть
[[ $OSTYPE != darwin* ]]
исключено-f
только из OSX.источник
Вот как можно получить фактический путь к файлу в MacOS / Unix, используя встроенный скрипт Perl:
Аналогично, чтобы получить каталог с символьным файлом:
источник
Ваш путь - это каталог, или это может быть файл? Если это каталог, все просто:
Однако, если это может быть файл, то это не будет работать:
потому что символическая ссылка может преобразоваться в относительный или полный путь.
В скриптах мне нужно найти реальный путь, чтобы я мог ссылаться на конфигурацию или другие скрипты, установленные вместе с ним, я использую это:
Вы можете установить
SOURCE
любой путь к файлу. По сути, пока путь является символической ссылкой, он разрешает эту символическую ссылку. Хитрость в последней строке цикла. Если разрешенная символическая ссылка является абсолютной, она будет использовать это какSOURCE
. Однако, если он является относительным, он будет предшествоватьDIR
для него, который был преобразован в реальное местоположение с помощью простого трюка, который я впервые описал.источник
источник
Примечание: Я считаю , что это быть твердым, портативный, готовое решение, которое неизменно длительный по той же причине.
Ниже приведен полностью POSIX-совместимый скрипт / функция, который, следовательно, кроссплатформенный (работает и в MacOS, чья
readlink
поддержка не поддерживается-f
на 10.12 (Sierra)) - он использует только функции языка оболочки POSIX и только POSIX-совместимые вызовы утилит ,Это переносимая реализация GNU
readlink -e
(более строгая версияreadlink -f
).Вы можете запустить скрипт с
sh
или подключите функцию вbash
,ksh
иzsh
:Например, внутри скрипта вы можете использовать его следующим образом, чтобы получить истинный каталог происхождения скрипта запуска с разрешенными символическими ссылками:
rreadlink
определение скрипта / функции:Код был адаптирован с благодарностью от этого ответа .
Я также создал здесь
bash
версию автономной утилиты на основе , которую вы можете установить , если у вас установлен Node.js.npm install rreadlink -g
Касательная к безопасности:
jarno , ссылаясь на функцию, гарантирующую, что встроенная функция
command
не скрывается псевдонимом или функцией оболочки с тем же именем, спрашивает в комментарии:Мотивация
rreadlink
обеспечения того, чтобы онcommand
имел первоначальное значение, состоит в том, чтобы использовать его для обхода (мягких) вспомогательных псевдонимов и функций, часто используемых для теневого копирования стандартных команд в интерактивных оболочках, таких как переопределениеls
для включения избранных параметров.Я думаю , что можно с уверенностью сказать , что если вы имеете дело с ненадежной, злонамеренного среде, заботясь о том
unalias
илиunset
- или, если на то пошло,while
,do
... - пересматриваются не является проблемой.Есть нечто , на что функция должна полагаться, чтобы иметь свое первоначальное значение и поведение - нет никакого способа обойти это.
То, что POSIX-подобные оболочки позволяют переопределять встроенные и даже языковые ключевые слова, по своей сути является угрозой безопасности (и вообще, писать параноидальный код сложно).
Чтобы конкретно решить ваши проблемы:
Функция опирается
unalias
иunset
имеет свое первоначальное значение. Было бы проблемой переопределить их как функции оболочки таким образом, чтобы это изменило их поведение; переопределение в качестве псевдонима не обязательно является проблемой, потому что цитирование (часть) имени команды (например,\unalias
) обходит псевдонимы.Однако, ссылаясь на это не вариант для оболочки ключевых слов (
while
,for
,if
,do
, ...) , и в то время как ключевые слова оболочки делают имеют преимущество над оболочками функций , вbash
иzsh
псевдонимами имеют наивысший приоритет, поэтому для защиты от оболочечных ключевого слова переопределениях вы должны работатьunalias
с их имена (хотя в неинтерактивныхbash
оболочках (таких как сценарии) псевдонимы по умолчанию не раскрываются - только еслиshopt -s expand_aliases
явно вызывается первым).Чтобы убедиться, что
unalias
- как встроенный - имеет первоначальное значение, вы должны\unset
сначала использовать его, что требует, чтобы оноunset
имело первоначальное значение:unset
это встроенная оболочка , поэтому для того, чтобы она вызывалась как таковая, вам необходимо убедиться, что она сама не переопределена как функция . Хотя вы можете обойти форму псевдонима с кавычками, вы не можете обойти форму функции оболочки - поймать 22.Таким образом, если вы не можете полагаться на то,
unset
чтобы иметь его первоначальное значение, насколько я могу судить, нет гарантированного способа защиты от всех злонамеренных переопределений.источник
[
как псевдоним вdash
иbash
и как функцию оболочки вbash
.while
как функцию вbash
,ksh
иzsh
(но неdash
), но только с помощьюfunction <name>
синтаксиса:function while { echo foo; }
работает (while() { echo foo; }
не). Однако это не будет скрыватьwhile
ключевое слово , потому что ключевые слова имеют более высокий приоритет, чем функции (единственный способ вызвать эту функцию - это as\while
). Вbash
иzsh
псевдонимы имеют более высокий приоритет, чем ключевые слова, поэтому переопределения псевдонимов ключевых слов затеняют их (ноbash
по умолчанию только в интерактивных оболочках, еслиshopt -s expand_aliases
явно не вызывается).Обычные сценарии оболочки часто должны находить свой «домашний» каталог, даже если они вызываются как символическая ссылка. Таким образом, скрипт должен найти свою «реальную» позицию всего за $ 0.
В моей системе печатается скрипт, содержащий следующее, что должно быть хорошим указанием на то, что вам нужно.
источник
Попробуй это:
источник
Так как я сталкивался с этим много раз на протяжении многих лет, и в этот раз мне понадобилась чисто переносимая версия bash, которую я мог бы использовать для OSX и Linux, я решил написать одну:
Живая версия живет здесь:
https://github.com/keen99/shell-functions/tree/master/resolve_path
но ради SO, вот текущая версия (я чувствую, что это хорошо проверено .. но я открыт для обратной связи!)
Может быть нетрудно заставить его работать на простой оболочке bourne (sh), но я не пытался ... Мне слишком нравится $ FUNCNAME. :)
вот классический пример, благодаря Brew:
используйте эту функцию, и она вернет -real- путь:
источник
Чтобы обойти несовместимость Mac, я придумал
Не отлично, но кросс-ОС
источник
python -c "from os import path; print(path.realpath('${SYMLINK_PATH}'));"
что, вероятно, имеет больше смысла. Тем не менее, к тому времени, когда вам нужно использовать Python из сценария оболочки, вам, вероятно, следует просто использовать Python и избавить себя от головной боли межплатформенных сценариев оболочки.dirname
,basename
иreadlink
внешние утилиты , а не обстреливать встроенные модули;dirname
иbasename
являются частью POSIX,readlink
нет.php
идет с OS X. Однако, хотя в основной части вопроса упоминается OS X, он не помечен как таковой, и он становится ясным что люди на разных платформах приходят сюда за ответами, поэтому стоит указать, что конкретно для платформы / не POSIX.Это преобразователь символических ссылок в Bash, который работает независимо от того, является ли ссылка каталогом или не каталогом:
Обратите внимание, что все
cd
иset
все происходит в подоболочке.источник
{}
вокруг()
не являются ненужными, если()
за именем функции нет. Bash принимает объявления функций без,()
потому что shell не имеет списков параметров в объявлениях и не делает вызовов с ними,()
поэтому объявления функций с()
не имеют большого смысла.Здесь я представляю то, что я считаю кроссплатформенным (по крайней мере, Linux и macOS) решением для ответа, который хорошо работает для меня в настоящее время.
Вот решение для macOS (только?). Возможно, лучше подходит для первоначального вопроса.
источник
Мой ответ здесь Bash: как получить реальный путь символической ссылки?
но вкратце очень удобно в скриптах:
Они являются частью GNU coreutils и подходят для использования в системах Linux.
Чтобы проверить все, мы помещаем символическую ссылку в / home / test2 /, исправляем некоторые дополнительные вещи и запускаем / вызываем ее из корневого каталога:
куда
источник
В случае, когда pwd не может использоваться (например, вызывать скрипты из другого места), используйте realpath (с или без dirname):
Работает как при вызове через (несколько) символьных ссылок, так и при непосредственном вызове скрипта - из любого места.
источник