13

I'm working on a HP-UX system and I want to find if there are any circular symbolic links.

So far I'm using the command:

ls -lrt  `find ./ -follow -type l`

But it's only doing ls -lrt on current directory as result.

What command should I use to find all circular symbolic links in a system?

voretaq7
  • 79,345
  • 17
  • 128
  • 213
Vladimir
  • 133
  • 1
  • 1
  • 4
  • 1) You are getting the current directory because the `find` command is either just printing `.` or not printing anything (so you are just running `ls -lrt` or `ls -lrt .`) Don't know enough about HP-UX `find` to tell you how to fix this (maybe it requires an explicit `-print`?). 2) What do you mean "circular"? `./a -> ./b` and `./b -> ./a`? What about `/home/foo/a -> /home`? Or `/home/foo/a -> /home/bar` and `/home/bar/b -> /home/foo`? – DerfK May 02 '11 at 20:19
  • By circular I meant any kind of link which can create a loop so all of the above. I'm trying with -print right now. – Vladimir May 02 '11 at 20:23
  • Also, why does not including `-follow` actually give me some real links are results? – Vladimir May 02 '11 at 21:28
  • Without `-follow`, `find` examines the link itself, not the file it points to. So `find . -type l` prints things that are links (because they are `-type l`) without even looking to see what they point at (which would be files or directories or other links that pointed to files or directories). – DerfK May 02 '11 at 21:51

1 Answers1

20

GNU find's manpage says that all POSIX finds are supposed to detect filesystem loops and emit error messages in these cases, and I have tested

find . -follow -printf ""

on GNU find, which was able to find loops of the form ./a -> ./b and ./b -> ./a printing the error

find: `./a': Too many levels of symbolic links
find: `./b': Too many levels of symbolic links

(this also worked on a->b->c->a)

Likewise, loops of the form ./foo/x -> .. and ./foo/a -> ./bar + ./bar/b -> ./foo printed the errors

find: File system loop detected; `./foo/a/b' is part of the same file system loop as `./foo'.
find: File system loop detected; `./bar/b/a' is part of the same file system loop as `./bar'.
find: File system loop detected; `./foo/x' is part of the same file system loop as `.'.

If you wanted to do something with the output other than read it, you would need to redirect it from stderr to stdout and pipe it to some script that can parse out the error messages.

DerfK
  • 19,313
  • 2
  • 35
  • 51
  • Does this mean that if there were any loops an error message would appear? – Vladimir May 02 '11 at 21:19
  • With GNU find and `-follow`, yes. – DerfK May 02 '11 at 21:22
  • Ok, but how does that explain getting just an `ls` instead of getting actual links when not using `-follow`? – Vladimir May 02 '11 at 21:30
  • 1
    That's how the shell works. You asked it to run the `ls` command using the output of your `find` command. Your `find` command didn't print anything, so your shell executed `ls` with nothing, which lists the current directory. – DerfK May 02 '11 at 21:53
  • DerfK's solution also finds cycles in Windows 7 by invoking it from a cygwin shell. – Don Gateley Aug 18 '13 at 22:17
  • Excellent Tip! However, when I ran that sequence it did find a loop but only displayed it as the relative path. Is there a way to force it to give absolute paths? – Andy Braham Apr 29 '17 at 14:06
  • Ok, how do we exit with code > 0 on the first circular detection? – Alexander Mills Dec 18 '18 at 07:09