tweeeetyのぶろぐ的めも

アウトプットが少なかったダメな自分をアウトプット<br>\(^o^)/

find+readlinkでディレクトリ内のシンボリックリンク一覧やその絶対パスを表示してみる

ほとんどお遊びな感じネタですが、
ちょっとだけfind+readlink使うことがあったのでそれも兼ねてのメモです。

最終目的はこんな感じ

コマンドで
・とあるディレクトリ内のシンボリックリンク一覧を取得したい
・その一覧の絶対パス絶対パス一覧で取得したい

ってことで、こんな感じの順番で最終目的に到達したいと思います

1.シンボリックリンクの一覧を表示
2.とある'1つの'シンボリックリンクリンク元を表示
3.1と2を使ってとあるディレクトリ内の各シンボリックリンク絶対パスを一覧で表示

0.前提

1〜3の前にこんな感じのディレクトリだったとします的な構造を示します

# pwd
/home/hoge/test_readlink

# tree
.
|-- a01
|   `-- a02
|       `-- a03
|           `-- a.txt
|-- b01
|   `-- b02
|       `-- b.txt
`-- c01
    |-- a_link.txt -> ../a01/a02/a03/a.txt
    `-- b_link.txt -> ../b01/b02/b.txt

1.シンボリックリンクの一覧を表示

こちらは簡単でfindコマンドと-type -lオプションを使います

# pwd 
/home/hoge/test_readlink

# find ./ -type l
./c01/b_link.txt
./c01/a_link.txt

2.とある'1つの'シンボリックリンクリンク元を表示

※ 念のため
# pwd 
/home/hoge/test_readlink

※ 一覧したファイルがシンボリックリンク
# ls c01
a_link.txt  b_link.txt

※ リンク元を相対パスで表示
※ 表示されているのはカレントディレクトリからのパスではなくリンクから見たリンク元です
# readlink c01/a_link.txt
../a01/a02/a03/a.txt

※ リンク元を絶対パスで表示
# readlink -f c01/a_link.txt
/home/hoge/test_readlink/a01/a02/a03/a.txt

3.1と2を使ってとあるディレクトリ内の各シンボリックリンク絶対パスを一覧で表示

これが意外にすんなりできませんでした(--;
2で'1つの'と強調しましたが、要するに一覧をいっきにreadlinkさせるやり方がすんなり出てこなかった。。

ってことで、失敗のほうも載せておきます

xargs使う(失敗例)

一覧はfindで簡単に出せたのでそれを次のコマンドへ渡せば良いか、
という単純な考えのコマンド。

# find ./ -type l | xargs /bin/readlink -f
/bin/readlink: extra operand `./c01/a_link.txt'
詳しくは `/bin/readlink --help' を実行して下さい.

xargsについてはこちらなんかに詳しく書いてあります。
今回の例で言うとxargsに「期待した結果」と「実際の結果」はこんな感じになってしまいます

※ 期待した結果
/bin/readlink -f ./c01/b_link.txt
/bin/readlink -f ./c01/a_link.txt

※ 実際の結果
/bin/readlink -f ./c01/b_link.txt ./c01/a_link.txt

xargs使う(成功例)

xargsの-nオプションを使うことで簡単にできました
(実際はxargsじゃダメなのかと思って結構他を探しちゃいました。。。)

# find ./ -type l | xargs -n1 /bin/readlink -f
/home/hoge/test_readlink/b01/b02/b.txt
/home/hoge/test_readlink/a01/a02/a03/a.txt

-n[number]で「number を最大限度に標準入力からできるだけ多くの引数を読み込んでコマンド文字列を実行する」らしいです。
オプションについてはこちらなんかを参考にさせて頂きました

find+for文でやる

↑の正解にたどりつく前にxargs以外の方法で探してしまって
変数に入れてループすりゃいいやって方法も思いついたのでそっちも載せておきます
何かの役に立ちますように(-人-)

# for slinks in $(find ./ -type l); do echo $slinks"|"`/bin/readlink $slinks`"|"`/bin/readlink -f $slinks` ; done
./c01/b_link.txt|../b01/b02/b.txt|/home/hoge/test_readlink/b01/b02/b.txt
./c01/a_link.txt|../a01/a02/a03/a.txt|/home/hoge/test_readlink/a01/a02/a03/a.txt

findの結果を$()で囲んで変数としてfor文で回します。
また、せっかくなので

リンク|リンク元(相対)|リンク元(絶対)

という感じで表示してみました。


理解してたつもりでも理解してないこと多いなーと思う今日このごろです。