Знайдіть лише місце призначення посилання


50

Для використання в оболонці-скрипті я шукаю спосіб командного рядка, щоб отримати призначення символічного посилання. Найближче, до якого я зайшов, - це те stat -N src, що дає результат src -> dst. Звичайно, я міг би проаналізувати вихід і отримати dst, але мені цікаво, чи існує якийсь прямий спосіб отримання пункту призначення.

Відповіді:


61

Іншим варіантом буде використання спеціально розробленої команди, readlinkякщо вона є.

Напр

$ readlink -f `command -v php`
/usr/bin/php7.1

21
Використовуйте, readlink -fякщо ви хочете знати останню ціль символьного посилання, а не лише наступну .
scai

Влучне зауваження! Забули це.
nikitautiu

11
Зауважте, що -fце непереносне розширення до GNU readlink.
Багамат

2
Коли посилання для читання не буде доступним? Дякую.
tommy.carstensen

2
@ tommy.carstensen readlink (1) було додано до GNU coreutils у 2003 році, тож ці дні, ймовірно, можуть залежати від нього практично у всіх системах, що використовують coreutils. (Cf. 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трапляється бути каталогом.


Я повністю скупився, stat --printf='%N\n'саме те, що я хочу, дивні котирування мене не турбують, їхні ж цитати rm та ln
інтерактивне

Це, мабуть, не є портативним, оскільки в Linux статтю GNU coreutils (1) має різні параметри і друкується link -> destу висновку. Рішення знахідки (1) слід перевірити, чи є воно з GNU findutils чи іншим чином ...
Йосип Родін

Будь ласка, не забудьте процитувати ваші змінні розширення. echo $fЗвичайно, це не дає того, що ви очікуєте, коли символьне посилання вказує на /*(так, це можливо)
Camusensei


1

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

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

Існують різні реалізації statкоманди як обгортки для stat/ lstatсистемних викликів. GNU не є корисним у цьому плані, але вбудований 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цього може слідувати лише один рівень симпосилання.


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

на моїй машині.

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