Reputation: 1260
This is my hierarchy:
aaaaaaaa
|_q
|_a.txt
|_w
|_l1
|_l2
l1
and l2
are symlinks to a.txt
.
I run this code to find all symlinks to a.txt
in the /aaaaaaaa
:
find ~/aaaaaaaa/ -exec ls -a {} ';' | grep '/home/khodor/aaaaaaaa/q/a.txt'
And it obviously doesn't work, cause I must compare realpath of file with path of a.txt
. In what way I should do this?
Upvotes: 4
Views: 1776
Reputation: 50750
If you have GNU/BSD find just use -samefile
primary.
$ find -L ~/aaaaaaaa/ -samefile ~/aaaaaaaa/q/a.txt
/home/oguz/aaaaaaaa/q/a.txt
/home/oguz/aaaaaaaa/w/l2
/home/oguz/aaaaaaaa/w/l1
Upvotes: 9
Reputation: 4688
Using find
with -type l
to search for symbolic links:
find aaaaaaaa -type l -exec sh -c '
for i; do
printf "%s -> %s\n" "$i" "$(readlink -f "$i")"
done
' sh {} +
The shell script prints link path and canonical path of the symlink using readlink -f
(but you could also use realpath
instead):
Example output:
aaaaaaaa/w/l1 -> /home/khodor/aaaaaaaa/q/a.txt
aaaaaaaa/w/l2 -> /home/khodor/aaaaaaaa/q/a.txt
Use grep
to filter the result using the absolute path, e.g.
find aaaaaaaa -type l -exec sh -c '
for i; do
printf "%s -> %s\n" "$i" "$(readlink -f "$i")"
done
' sh {} + | grep '/home/khodor/aaaaaaaa/q/a.txt$'
Note the $
at the end of the pattern to match the end of the line.
Upvotes: 1
Reputation: 2544
referenceid=$(stat -Lc '%d-%i' /home/khodor/aaaaaaaa/q/a.txt)
find ~/aaaaaaaa/ -type l -print0 | while IFS= read -r -d '' filename
do
if [ "$(stat -Lc '%d-%i' "$filename")" = "$referenceid" ]
then
printf -- '%s\n' "$filename"
fi
done
This initially gets a unique ID for a base file, e.g. /home/khodor/aaaaaaaa/q/a.txt
. The ID is computed from the device ID and the inode, using stat
.
Then it parses your folder using file
, limited to symbolic links (thanks to -type l
), and for each filename it gets the device ID and inode using stat
again, using its -L
option that dereferences the link before fetching the ID.
For each device ID and inode that matches the reference ID, it prints the filename.
Upvotes: 1