2

How can I check if there is a link from the current file on Linux? Say, I have:

touch foo
ln -s foo bar
ll foo bar
 bar -> foo
 foo

Now, I want to know, if there are any file linked from foo:e.g.

$magic-command foo
foo<-bar
terdon
  • 242,166
BaRud
  • 1,639
  • 2
  • 17
  • 26

2 Answers2

3

With GNU find, you can do:

find -L /  -xtype l -prune -samefile foo -exec ls -ld {} +

That will find all the files of type symlinks which eventually resolve to the same file as foo. That will also include symlinks to symlinks or hardlinks to foo1.

With -L, symlinks are followed. We want that to find files linked to foo, but we don't want to follow symlink when descending the directory tree. Hence the -prune that stops descending into symlinks.

With zsh, you can do:

ls -ld /**/*(@De:'[[ $REPLY -ef foo ]]':)

If you're only interested in symlinks.


1 Finding only files that are symlinks to foo would be more complicated. The -samefile/-ef compare the device and inode numbers returned by the stat() system call, that is after all symlinks have been resolved (by the system). What you would want is check for links whose target's directory is the same as that of foo and base name is foo.

With zsh, that would be:

zmodload zsh/zstat
links_to_thefile() {
  local file link
  file=${1-$REPLY}
  zstat -L -A link +link -- $file || return
  [[ $link:t = $thefile:t ]] || return
  case $link in
    (/*) file=$link;;
    (*)  file=$file:h/$link
  esac
  [[ $file:h -ef $thefile:h ]]
}

thefile=foo
ls -ld /**/*(@D+links_to_thefile)

Or with GNU tools (find and shell (bash)):

find / -type l  \( -lname foo -o -lname '*/foo' \) -printf '%p\0%l\0' |
  while IFS= read -rd '' file && IFS= read -rd '' link; do
    [[ $link = /* ]] || link=${file%/*}/$link
    [[ ${link%/*} -ef . ]] && printf '%s\n' "$file"
  done
0

stat doesn't count symlink counts, hardlinks though - if that helps.

There's no way to resolve what you're asking.