Вопрос или проблема
Для использования в shell-скрипте я ищу способ в командной строке, чтобы получить назначение символической ссылки. Ближе всего я подошел к этому с помощью stat -N src
, который выводит src -> dst
. Конечно, я мог бы разбить вывод и получить dst
, но мне интересно, существует ли какой-то прямой способ получить назначение.
Другой вариант — использовать специально разработанную команду readlink
, если она доступна.
Например:
$ readlink -f `command -v php`
/usr/bin/php7.1
Флаг -f
имеет такую функциональность: “канонизировать, следуя каждой символической ссылке в каждом компоненте данного имени рекурсивно; все, кроме последнего компонента, должны существовать”. Это делает вывод этой команды потенциально отличным от stat -c'%N' src
, который не следует за каждой символической ссылкой.
На 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
оказывается каталогом.
Это можно сделать с помощью GNU find
: find src -prune -printf "%l\n"
.
Команда realpath
из пакета coreutils
,
как указано на странице руководства по команде readlink
.
например:
realpath /bin/python
выводит
/usr/bin/python2.7
на моей машине.
На системе, где у меня нет команд 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
это может следовать только по одному уровню символической ссылки.
Портативная чистая Bash realpath
bash_realpath() {
# выводит разрешенный путь
# @параметры
# 1: путь для разрешения
# @возвращает
# &1: разрешенный путь ссылки
local path="${1}"
while [[ -L ${path} && "$(ls -l "${path}")" =~ -\>\ (.*) ]]
do
path="${BASH_REMATCH[1]}"
done
echo "${path}"
}
Портативно: безуспешно, кроме использования эвристик для разбора вывода 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
Добавил версию на чистом sh, надеясь, что она будет более портативной, если bash
не установлен:
$ cat ./realpath.sh
#!/usr/bin/env sh
bash_realpath() {
# выводит разрешенный путь
# @параметры
# 1: путь для разрешения
# @возвращает
# &1: разрешенный путь ссылки
for path;do
while [ -L "${path}" ]
do
path="$(\ls -l "${path}" | awk '{print $NF}')"
done
which "${path}"
done
}
bash_realpath "$@"
Пример использования :
$ ./realpath.sh $(which gcc python)
/usr/bin/x86_64-linux-gnu-gcc-6
/usr/bin/python2.7
.
Ответ или решение
Определение назначения символической ссылки в скрипте
В современном мире информационных технологий символические ссылки играют важную роль в управлении файловыми системами. Эти ссылки позволяют создать псевдонимы для файлов или каталогов, упрощая их использование и организацию. Однако иногда возникает необходимость определить, куда именно указывает символическая ссылка. В этой статье мы рассмотрим несколько методов, которые помогут в этом деле, с использованием различных инструментов и программных средств.
Теория
Символическая ссылка (или symlink) — это специальный тип файла, который указывает на другой файл или каталог. В отличие от жестких ссылок, символические ссылки являются отдельными файлами. Они могут указывать на любые файлы или каталоги, включая те, которые находятся на других файловых системах. Самый важный аспект символической ссылки заключается в том, что она хранит путь к целевому объекту, но не обладает его содержимым.
Определение целевого объекта символической ссылки является часто встречающейся задачей в различных сценариях автоматизации и администрирования систем. Она может быть критически важной при отладке, миграции данных и других операциях, связанных с поддержанием целостности данных.
Примеры
-
Команда
readlink
: Один из наиболее простых способов выяснить, куда указывает символическая ссылка — это использовать утилитуreadlink
. Например:readlink symlink_name
Если необходимо получить полный канонический путь, включая все промежуточные символические ссылки, используется опция
-f
:readlink -f symlink_name
Однако стоит отметить, что опция
-f
недоступна в некоторых системах, таких как macOS по умолчанию. -
Команда
stat
: В UNIX-системах командаstat
позволяет получать информацию о файле или файловой системе, включая данные о символических ссылках. На разных операционных системах синтаксис этой команды может варьироваться:-
Для GNU систем:
stat -c %N symlink_name
-
В macOS и BSD-подобных системах:
stat -f %Y symlink_name
-
-
Использование
find
: Эта команда также может использоваться для определения цели символической ссылки:find symlink_name -maxdepth 0 -printf %l
Важно отметить использование
-maxdepth 0
для избежания погружения в каталоги, если symlink указывает на директорию. -
Реализация на Python: На системах, где нет доступа к
readlink
илиstat
, можно воспользоваться Python-скриптом:#!/usr/bin/env python import os import 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)
Этот скрипт определяет путь к файлу-цели, даже если символическая ссылка является относительной.
Применение
Выбор конкретного инструмента зависит от контекста использования. Для системных администраторов, работающих преимущественно в среде Linux, readlink
и stat
будут наиболее предпочтительными инструментами благодаря своей простоте и быстродействию. В случаях, когда необходима кроссплатформенная совместимость, Python-скрипт может стать незаменимым помощником.
Кроме того, знание подобного функционала может быть критически важным при разработке скриптов для автоматизации, в которых символические ссылки служат для упрощения управления зависимостями, подключения библиотек или переходов между различными версиями программного обеспечения. Например, в большом проекте, где множество сервисов ссылаются на динамически обращаемые библиотеки, возможность быстро определить и скорректировать пути может сэкономить часы отладки и предотвращения ошибок.
Заключая, важно учитывать, что каждая система и каждый сценарий требуют своего подхода. Знание различных методов определения назначения символических ссылок и правильное их использование обеспечивают большую гибкость и эффективность в администрировании и разработке программного обеспечения.