シンボリックリンクチェーンを一覧表示する方法


36

この例を考えます:

mkdir a
ln -s a b
ln -s b c
ln -s c d

私が実行した場合:

ls -l d

表示されます:

d -> c

代わりlsに表示する方法や他のLinuxコマンドはありd -> c -> b -> aますか?


私はこれをstackoverflow.com/questions/2320277/としてクロス投稿しました …気にしないでください。
ポール

回答:


65

ただ使用するnamei

$ namei d
f: d
 l d -> c
   l c -> b
     l b -> a
       d a

5
TIL。これは素晴らしいコマンドです。upvotes
トム・オコナー

これは、opで要求されたリンクの完全なチェーンを示すため、受け入れられた答えでなければなりません。さらに、に類似しlsたディレクトリ全体をリストするために使用できます。ありがとう!
恐怖症

確かに、この投稿を再訪していたとnameiは素晴らしいコマンドです!
カレセル

「which」コマンドで使用して、プログラムの実際の使用法を見つけます。$ namei `which java`
pdem

18

readlink -e <link>

readlink [オプション] ...ファイル

  • -e、--
    canonicalize -existing canonicalize指定された名前のすべてのコンポーネントのすべてのシンボリックリンクを再帰的にたどることにより、すべてのコンポーネントが存在する必要があります
$ mkdir testlink
$ cd testlink
pjb@pjb-desktop:~/testlink$ ln -s c b
pjb@pjb-desktop:~/testlink$ ln -s b a
pjb@pjb-desktop:~/testlink$ ls -l 
total 0
lrwxrwxrwx 1 pjb pjb 1 2010-02-23 08:48 a -> b
lrwxrwxrwx 1 pjb pjb 1 2010-02-23 08:48 b -> c
pjb@pjb-desktop:~/testlink$ echo foo > c
pjb@pjb-desktop:~/testlink$ cat a
foo
pjb@pjb-desktop:~/testlink$ readlink -e a
/home/pjb/testlink/c

注:readlink a自体はbを返します

注#2:find -lとともに、チェーンを一覧表示するユーティリティはperlで簡単に記述できますが、ループを検出するのに十分スマートでなければなりません

ループがある場合、readlinkは何も出力しません。これは行き詰まるよりも良いと思います。

pjb@pjb-desktop:~/testlink$ ln -sf a c
pjb@pjb-desktop:~/testlink$ ls -l 
total 0
lrwxrwxrwx 1 pjb pjb 1 2010-02-23 08:48 a -> b
lrwxrwxrwx 1 pjb pjb 1 2010-02-23 08:48 b -> c
lrwxrwxrwx 1 pjb pjb 1 2010-02-23 09:03 c -> a
pjb@pjb-desktop:~/testlink$ readlink -e a
pjb@pjb-desktop:~/testlink$ # (note: no output)

OS Xの場合:brew install coreutilsおよびgreadlink -e <link>
Jose Alban

3

Bashの再帰関数は次のとおりです。

chain() { export chain; local link target; if [[ -z $chain ]]; then chain="$1"; fi; link=$(stat --printf=%N $1); while [[ $link =~ \-\> ]]; do target="${link##*\`}"; target="${target%\'}"; chain+=" -> $target"; chain "$target"; return; done; echo "$chain"; unset chain; }

複数の行で:

chain() {
    export chain
    local link target
    if [[ -z $chain ]]
    then
        chain="$1"
    fi
    link=$(stat --printf=%N "$1")
    while [[ $link =~ \-\> ]]
    do
        target="${link##*\`}"
        target="${target%\'}"
        chain+=" -> $target"
        if [[ ! $target =~ / && $1 =~ / ]]
        then
            target="${1%/*}/$target"
        fi
        chain "$target"
        return
    done
    echo "$chain"
    unset chain
}

例:

$ chain d
d -> c -> b -> a
$ chain c
c -> b -> a
$ chain a
a

それは必要としstat(1)、いくつかのシステム上に存在していない可能性があります。

名前にバッククォート、一重引用符、または「->」が含まれていると失敗します。シンボリックリンクループでループに陥ります(これは、Bash 4の連想配列を使用して解決できます)。既に使用されているかどうかに関係なく、「チェーン」と呼ばれる変数をエクスポートします。

他の問題がある可能性があります。

編集:

いくつかの相対シンボリックリンクの問題を修正しました。まだ機能しないものもありますが、以下のバージョンではリンクのターゲットが存在する必要はありません。

readlinkを使用するバージョンを追加しました。

chain ()
{
    export chain;
    local target;
    if [[ -z $chain ]]; then
        chain="$1";
    fi;
    target=$(readlink "$1");
    while [[ $target ]]; do
        chain+=" -> $target";
        if [[ ! $target =~ / && $1 =~ / ]]
        then
            target="${1%/*}/$target"
        fi
        chain "$target";
        return;
    done;
    echo "$chain";
    unset chain
}

私はあなたのスクリプトをテストしましたが、実際に動作しますが、私はもっとシンプルなものを好むので、不完全であっても他の答えを受け入れました。
カレセル

1
素敵なスクリプト。チェーン全体を見たい場合がありますが、それreadlinkを見せていないようです。Ubuntuの上のJavaは、次のとおりです。/usr/bin/java -> /etc/alternatives/java -> /usr/lib/jvm/java-6-openjdk/jre/bin/java
ステファンLasiewski

0

nameiの出力を次のようなもので後処理するか、awk必要なgrep行だけを取得することができます。

namei d | awk '$1=="l"'

または

namei d | egrep -e "->"
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.