Найти только пункт назначения символической ссылки

50

Для использования в shell-скрипте я ищу способ командной строки, чтобы получить назначение символической ссылки. Самое близкое, что я дошел, это то stat -N src, что выводит src -> dst. Конечно, я мог бы проанализировать вывод и получить dst, но мне интересно, есть ли какой-то прямой способ получить пункт назначения.

Геррит
источник

Ответы:

61

Другой вариант - использовать специально разработанную команду, readlinkесли она доступна.

Например

$ readlink -f `command -v php`
/usr/bin/php7.1
nikitautiu
источник
21
Используйте, readlink -fесли вы хотите знать последнюю цель символической ссылки, а не только следующую .
Scai
Хорошая точка зрения! Забыл это.
Никитаутиу
11
Обратите внимание, что -fэто непереносимое расширение для GNU readlink.
Багамат
2
Когда ссылка будет недоступна? Благодарю.
tommy.carstensen
2
@ tommy.carstensen readlink (1) была добавлена ​​в GNU coreutils в 2003 году, поэтому в наши дни вы, вероятно, можете зависеть от нее практически на всех системах, использующих coreutils. (См. Git.savannah.gnu.org/cgit/coreutils.git/commit/src/… )
Иосип Родин
16

В Mac OS X и FreeBSD / NetBSD / и т. Д. его:

stat -f %Y <filename>

В более общем смысле, я думаю, что решение (stat --printf =% N использует странные кавычки):

ls -l b | sed -e 's/.* -> //'

Пример:

# ln -s a b
# stat -f %Y b
a

Другой метод:

# find b -maxdepth 0 -printf %l
a#

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

# f=$(find b -maxdepth 0 -printf %l)
# echo $f
a

-maxdepthНеобходимо для предотвращения findот вхождения в каталоги , если bслучается быть каталогом.

Coroos
источник
Я полностью просмотрел, stat --printf='%N\n'это именно то, что я хочу, странные цитаты меня не беспокоят, их те же самые цитаты rm и ln - интерактивное использование
ThorSummoner
Это, очевидно, не переносимо, потому что в Linux stat (1) из GNU coreutils имеет разные параметры и link -> destвыводится в вывод. Решение find (1) должно быть проверено, если оно с GNU findutils или иным образом ...
Josip Rodin
Пожалуйста, не забудьте процитировать ваши расширения переменных, echo $fконечно, не дает того, что вы ожидаете, когда символическая ссылка указывает на /*(да, это возможно)
Camusensei
3

Это может быть сделано с помощью GNU find: find src -prune -printf "%l\n".

Геррит
источник
1

Портативно: не повезло, кроме использования эвристики для анализа вывода ls -l или использования perl -le 'print readlink("some-file")'

в некоторых системах есть readlinkкоманда, в некоторых есть -fвозможность получить абсолютный путь.

Существуют различные реализации в statкоманде в качестве обертки для stat/ lstatсистемных вызовов. GNU one бесполезен в этом отношении, но встроенный в zsh больше:

zmodload zsh/stat
stat +link the-link

Тем не менее, с zsh вы можете получить абсолютный путь к файлу (удаляет каждый компонент символической ссылки) с :Aмодификатором (применяется к раскрытию переменных, расширению истории и глобализации:

~$ gstat -c %N b
`b' -> `a'
~$ var=b
~$ echo $var:A
/home/me/a
~$ echo b(:A)
/home/me/a
~$ echo ?(@:A)
/home/me/a
Стефан Шазелас
источник
1

В системе, где у меня нет команд readlinkили statкоманд, но у меня есть Python 2.x, я использую короткий скрипт:

#!/usr/bin/env python

import os, sys

if __name__ == "__main__":
    src = sys.argv[1]
    target = os.readlink(src)
    if not os.path.isabs(target):
            target = os.path.abspath(os.path.join(os.path.dirname(src), target))
    print target

Обратите внимание, что в отличие от readlink -fэтого может следовать только один уровень символической ссылки.

rakslice
источник
1

Портативный чистый Bash RealPath

bash_realpath() {
  # print the resolved path
  # @params
  # 1: the path to resolve
  # @return
  # &1: the resolved link path

  local path="${1}"
  while [[ -L ${path} && "$(ls -l "${path}")" =~ -\>\ (.*) ]]
  do
    path="${BASH_REMATCH[1]}"
  done
  echo "${path}"
}
Леа Гри
источник
0

realpathкоманда coreutilsпакета,

как указано readlinkна странице руководства команды.


например:

realpath /bin/python

выходы

/usr/bin/python2.7

на моей машине.


источник