2015-10-21 20 views
2

Нахождение Java двоичных файлов может быть болезненным:Как перечислить всех членов символической цепочки?

  • which java дает /usr/bin/java
  • lh $(which java) дает /usr/bin/java -> /etc/alternatives/java
  • lh /etc/alternatives/java дает /etc/alternatives/java -> /usr/lib/jvm/jdk1.8.0_66/bin/java

Есть ли способ, чтобы автоматически следовать символической ссылке цепь и печать все участники? например whichfollow или follow /usr/bin/java может дать:

/usr/bin/java 
-> /etc/alternatives/java 
-> /usr/lib/jvm/jdk1.8.0_66/bin/java 
+0

Возможный дубликат [Как разрешить символические ссылки в сценарии оболочки] (http://stackoverflow.com/questions/7665/how-to-resolve-symbolic-links-in-a-shell-script) –

+0

@ AnthonyGeoghegan: Это не дубликат, потому что этот вопрос касается печати _chain_ символических ссылок. – mklement0

+1

@ mklement0 Я понял это после (а затем предоставил альтернативный ответ), но я не думаю, что можно развязать. В любом случае, я оставил комментарий, поскольку ответы по соответствующему вопросу все равно были бы полезны для людей, заинтересованных в том, как разрешить символические ссылки. Отличный ответ, сам. –

ответ

1

Вы можете использовать readlink с while цикла. Ниже функция будет работать:

function follow { 
    path="$1" 
    echo "$path" 
    while path=$(readlink "$path"); do 
    echo "-> $path" 
    done 
} 

follow "/usr/bin/java" 
+0

Это не работает с относительными ссылками, если они не находятся в текущем рабочем каталоге (или, иногда, каталоге кузена, если в начале есть один или несколько компонентов '..'. –

4

В дополнении к команде readlink пользователей GNU/Linux можно использовать команду namei из util-linux пакета. Согласно его странице руководства:

namei использует свои аргументы как пути к любому типу Unix-файла (символические ссылки, файлы, каталоги и т. Д.). namei затем следует каждому пути до тех пор, пока не будет найдена конечная точка (файл, каталог, узел устройства и т. д.). Если он находит символическую ссылку, он показывает ссылку и начинает следовать за ней, отступая от вывода, чтобы показать контекст.

Его выход не так хороша, как хотелось бы, но это показывает, каждый путь компоненты и показывает, если его каталог, символическая ссылка, сокет, блочное устройство, символьное устройство, FIFO (именованный канал) или обычный файл ,

Пример использования:

$ namei /usr/bin/java 

f: /usr/bin/java 
d/
d usr 
d bin 
l java -> /etc/alternatives/java 
    d/
    d etc 
    d alternatives 
    l java -> /usr/lib/jvm/jre-1.7.0-openjdk/bin/java 
    d/
    d usr 
    d lib 
    d jvm 
    l jre-1.7.0-openjdk -> java-1.7.0-openjdk-1.7.0.85/jre 
     d java-1.7.0-openjdk-1.7.0.85 
     d jre 
    d bin 
    - java 
+1

Отличный материал, выглядит как' namei 'предустановлен на многих дистрибутивах и может отображать дополнительную информацию, такую ​​как бит режима. Единственное, что я хотел сделать, это разрешить относительные целевые пути к абсолютным, без этого не всегда очевидно, к какому пути относится, особенно с '..'. – mklement0

3

Примечание: namei (см Anthony Geoghegan's answer) и chase (см Toby Speight's answer) большие Linux варианты; этот ответ предлагает:
* кросс-платформенный решения
* печать из абсолютных путей для каждый шаг цепи, даже если алиасы определяются с относительными путями.

  • Рассмотрим typex utility (написанный мной), который печатает символическую ссылку цепь данной утилиты в $PATH, используя абсолютные путей в каждом шаге (typex также обеспечивает дополнительную информацию, аналогичную, но более обширный, чем type).
    • Простейшая установка, с узлом.JS установлены: npm install typex -g
    • Пример (обратите внимание, как информация о версии, полученные с --version, прилагается - не будет работать на java, однако, который использует -version):
 $ typex awk 
     BINARY: /usr/bin/[email protected] -> /etc/alternatives/[email protected] -> /usr/bin/gawk [GNU Awk 4.0.1] 
  • rreadlink - это утилита нижнего уровня (написанная мной), которая печатает цепочку символических ссылок как абсолютные пути для любого заданного пути к файловой системе.

    • Простейшее установка, с Node.js установлен: npm install rreadlink -g
    • Пример:

      $ rreadlink -1 "$(which awk)" 
      /usr/bin/awk 
      /etc/alternatives/awk 
      /usr/bin/gawk 
      
  • Ниже rreadlinkchain(), A полностью POSIX-совместимый скрипт/функция - она ​​использует только POSIX shell language features и только вызовы утилиты, совместимые с POSIX. Это совместимый с POSIX вариант функции bash, лежащий в основе двух утилит выше, и был с благодарностью адаптирован от this answer; применены к примеру: rreadlinkchain "$(which java)"

ноты Совместимость:
typex и rreadlink, при установке из реестра НПМ, поддерживают как OS X и Linux, но они , вероятно, также работают на системах BSD с bash, при установке вручную.
Как указано, rreadlinkchain()функция ниже полностью совместима с POSIX и должна работать на большинстве Unix-подобных платформ.

#!/bin/sh 

## ------- 
# SYNOPSIS 
# rreadlinkchain <symLink> 
# DESCRIPTION 
# Recursive readlink: prints the CHAIN OF SYMLINKS from the input 
# file to its ultimate target, as ABSOLUTE paths, with each path on a separate 
# line. 
# Only the ultimate target's path is canonical, though. 
# A broken symlink in the chain causes an error that reports the 
# non-existent target. 
# An input path that is not a symlink will print its own canonical path. 
# LIMITATIONS 
# - Won't work with filenames with embedded newlines or filenames containing 
#  the string ' -> '. 
# COMPATIBILITY 
# Fully POSIX-compliant. 
# EXAMPLES 
#  # Print the symlink chain of the `git` executable in the $PATH. 
# rreadlinkchain "$(which git)" 
# # Ditto, using single-line `ls -l`-style format ('[email protected] -> b') 
# rreadlinkchain "$(which git)" | sed -nE -e '$!{a\'$'\n''@ -> ' -e '}; p' | tr -d '\n' 
# THANKS 
# https://stackoverflow.com/a/1116890/45375 
rreadlinkchain() (# execute in *subshell* to localize the effect of `cd`, ... 

    target=$1 targetDir= targetName= CDPATH= 

    # Try to make the execution environment as predictable as possible: 
    # All commands below are invoked via `command`, so we must make sure that 
    # `command` itself is not redefined as an alias or shell function. 
    # (Note that command is too inconsistent across shells, so we don't use it.) 
    # `command` is a *builtin* in bash, dash, ksh, zsh, and some platforms do not 
    # even have an external utility version of it (e.g, Ubuntu). 
    # `command` bypasses aliases and shell functions and also finds builtins 
    # in bash, dash, and ksh. In zsh, option POSIX_BUILTINS must be turned on for 
    # that to happen. 
    { \unalias command; \unset -f command; } >/dev/null 2>&1 
    [ -n "$ZSH_VERSION" ] && options[POSIX_BUILTINS]=on # make zsh find *builtins* with `command` too. 

    while :; do 
     # Unless the file is a symlink OR exists, we report an error - note that using `-e` with a symlink reports the *target*'s existence, not the symlink's. 
    [ -L "$target" ] || [ -e "$target" ] || { command printf '%s\n' "ERROR: '$target' does not exist." 1>&2; return 1; } 
     # !! We use `cd` to change to the target's folder 
     # !! so we can correctly resolve the full dir. path. 
    command cd "$(command dirname -- "$target")" # note: cd "" is the same as cd . - i.e., a no-op. 
    targetDir=$PWD 
    targetName=$(command basename -- "$target") 
    [ "$targetName" = '/' ] && targetName='' # !! curiously, `basename /` returns '/' 
    done=0 
    if [ ! -L "$targetName" ]; then 
     # We've found the ultimate target (or the input file wasn't a symlink to begin with). 
     # For the *ultimate* target we want use `pwd -P` to make sure we use the actual, physical directory, 
     # (not a symlink) to get the *canonical* path. 
     targetDir=$(command pwd -P) 
     done=1 
    fi 
     # Print (next) path - note that we manually resolve paths ending 
     # in /. and /.. to make sure we have a normalized path. 
    if [ "$targetName" = '.' ]; then 
     command printf '%s\n' "${targetDir%/}" 
    elif [ "$targetName" = '..' ]; then 
     # Caveat: something like /var/.. will resolve to /private (assuming 
     # /[email protected] -> /private/var), i.e. the '..' is applied AFTER canonicalization. 
     command printf '%s\n' "$(command dirname -- "${targetDir}")" 
    else 
     command printf '%s\n' "${targetDir%/}/$targetName" 
    fi 
     # Exit, if we've hit the non-symlink at the end of the chain. 
    [ "$done" = 1 ] && break 
    # File is symlink -> continue to resolve. 
    # Parse `ls -l` output, which, unfortunately, is the only POSIX-compliant 
    # way to determine a symlink's target. Hypothetically, this can break with 
    # filenames containig literal ' -> ' and embedded newlines. 
    target=$(command ls -l -- "$targetName") 
    target=${target#* -> } 
    done 
) 

rreadlinkchain "[email protected]" 
1

Рассмотрите возможность установки chase:

Пример вывода:

$ chase --verbose /usr/bin/java 
/usr/bin/java 
-> /etc/alternatives/java 
-> /usr/lib/jvm/java-7-openjdk-amd64/jre/bin/java 
/usr/lib/jvm/java-7-openjdk-amd64/jre/bin/java 

Описание Пакет:

Пакет: Погоня
Государственный: установлен
Автоматически устанавливается: нет
Версия: 0,5.2-4build2
Приоритет: опционно
Раздел: Вселенная/Utils
Сопровождающий: Ubuntu Разработчики
Архитектура: amd64
несжатого Размер: 61,4 K
Зависит: libc6 (> = 2.3.4), libgc1c2 (> = 1: 7.2d)
Конфликты: погоня
Описание: Следуйте символические ссылки и распечатать его целевой файл
Chase это небольшая утилита для отслеживания фактического файл, который указывает символьная ссылка на - чеканка линке, если вы будете. Результатом успешного запуска является файл, который не является символической ссылкой.

+0

Полезно знать, также приятно видеть, что' chase' имеет обнаружение симлинковых циклов. В отличие от 'namei',' chase' похвально всегда печатает целевой путь _ultimate_ как путь _absolute_, но я желаю также сделал это для _intermediate_, чьи цели определены как _relative_ пути (возможно, в _addition_ к относительному пути), так как не всегда очевидно, к какому пути относится, особенно с '..' – mklement0

 Смежные вопросы

  • Нет связанных вопросов^_^