次のコマンドラインスニペットを検討してください。
$ cd /tmp/
$ mkdir dirA
$ mkdir dirB
$ echo "the contents of the 'original' file" > orig.file
$ ls -la orig.file
-rw-r--r-- 1 $USER $USER 36 2010-12-26 00:57 orig.file
# create symlinks in dirA and dirB that point to /tmp/orig.file:
$ ln -s $(pwd)/orig.file $(pwd)/dirA/
$ ln -s $(pwd)/orig.file $(pwd)/dirB/lorig.file
$ ls -la dirA/ dirB/
dirA/:
total 44
drwxr-xr-x 2 $USER $USER 4096 2010-12-26 00:57 .
drwxrwxrwt 20 root root 36864 2010-12-26 00:57 ..
lrwxrwxrwx 1 $USER $USER 14 2010-12-26 00:57 orig.file -> /tmp/orig.file
dirB/:
total 44
drwxr-xr-x 2 $USER $USER 4096 2010-12-26 00:58 .
drwxrwxrwt 20 root root 36864 2010-12-26 00:57 ..
lrwxrwxrwx 1 $USER $USER 14 2010-12-26 00:58 lorig.file -> /tmp/orig.file
この時点で、readlink
を使用して「オリジナル」とは何かを確認できます(まあ、ここでの通常の用語は「ターゲット」または「ソース」のどちらかです。まあ、だから私はそれを単に「オリジナル」と呼ぶ)シンボリックリンクのファイル、すなわち.
$ readlink -f dirA/orig.file
/tmp/orig.file
$ readlink -f dirB/lorig.file
/tmp/orig.file
...しかし、私が知りたいのは-「元の」ファイルで実行でき、それを指すすべてのシンボリックリンクを見つけることができるコマンドはありますか?言い換えれば、(疑似)のようなものです:
$ getsymlinks /tmp/orig.file
/tmp/dirA/orig.file
/tmp/dirB/lorig.file
コメントありがとうございます、
乾杯!
ターゲットファイルには、どのソースファイルがそれを指しているかに関する情報が含まれていないため、このコマンドは見たことがなく、簡単な作業ではありません。
これは「ハード」リンクに似ていますが、少なくともそれらは常に同じファイルシステム上にあるため、find -inode
それらをリストします。ソフトリンクはファイルシステムを横断できるため、より問題があります。
あなたがしなければならないことは基本的にls -al
階層全体のすべてのファイルで、grep
を使用して-> /path/to/target/file
。
たとえば、これは私のシステムで実行したものです(読みやすいようにフォーマットされています-実際の出力では、最後の2行は実際にはone行にあります):
pax$ find / -exec ls -ald {} ';' 2>/dev/null | grep '\-> /usr/share/applications'
lrwxrwxrwx 1 pax pax 23 2010-06-12 14:56 /home/pax/applications_usr_share
-> /usr/share/applications
GNU find
を使用すると、ファイルにハードリンクまたはシンボリックリンクされているファイルが検索されます。
find -L /dir/to/start -samefile /tmp/orig.file
シンボリックリンクは、特定の宛先を指しているものを追跡しません。したがって、次のように、各シンボリックリンクが目的の宛先を指しているかどうかを確認するよりも良い方法はありません。
for i in *; do
if [ -L "$i" ] && [ "$i" -ef /tmp/orig.file ]; then
printf "Found: %s\n" "$i"
fi
done
これが私が思いついたものです。これを_readlink -f
_を持たないOS Xで実行しているため、ヘルパー関数を使用して置き換える必要がありました。適切な_readlink -f
_があれば、代わりにそれを使用できます。また、この場合、while ... done < <(find ...)
の使用は厳密には必要ありません。単純な_find ... | while ... done
_が機能します。しかし、ループ内で変数を設定するようなことをしたい場合(一致するファイルの数など)、while
ループがサブシェルで実行されるため、パイプバージョンは失敗します。最後に、_find ... -type l
_を使用しているため、ループはシンボリックリンクでのみ実行され、他の種類のファイルでは実行されないことに注意してください。
_# Helper function 'cause my system doesn't have readlink -f
readlink-f() {
orig_dir="$(pwd)"
f="$1"
while [[ -L "$f" ]]; do
cd "$(dirname "$f")"
f="$(readlink "$(basename "$f")")"
done
cd "$(dirname "$f")"
printf "%s\n" "$(pwd)/$(basename "$f")"
cd "$orig_dir"
}
target_file="$(readlink-f "$target_file")" # make sure target is normalized
while IFS= read -d '' linkfile; do
if [[ "$(readlink-f "$linkfile")" == "$target_file" ]]; then
printf "%s\n" "$linkfile"
fi
done < <(find "$search_dir" -type l -print0)
_
Gordon Davissonのコメントに触発されました。これは別の答えに似ていますが、execを使用して目的の結果を得ました。元のファイルの場所を知らなくてもシンボリックリンクを見つけることができるものが必要でした。
find / -type l -exec ls -al {} \; | grep -i "all_or_part_of_original_name"