10

How do I (recursively) detect all symlinks in a directory that identify their target in an absolute as opposed to in a relative way?

Since these links are very likely to break when an entire directory tree is moved I would like to have a way of identifying them.

Even relative links may break if the directory tree is moved (if they happen to point outside the root of the directory tree), but I think this is addressed in this question.

1

2 Answers 2

18

To find absolute links, you can use find's -lname option if your find supports that (it's available at least in GNU find, on FreeBSD and macOS):

find . -type l -lname '/*'

This asks find to print the names of files which are symbolic links and whose content (target) matches /* using shell globbing.

Strictly speaking, POSIX specifies that absolute pathnames start with one / or three or more /; to match that, you can use

find . -lname '/*' ! -lname '//*' -o -lname '///*'

On what systems is //foo/bar different from /foo/bar? has more details on that.

(Thanks to Sato Katsura for pointing out that -lname is GNU-specific, to fd0 for mentioning that it's actually also available on at least FreeBSD and macOS, and to Stéphane Chazelas for bringing up the POSIX absolute pathname definition.)

2
  • I was about to post: find ./ -t l -exec ls -l {} \; which should be a safe alternative. It would be easy to parse its output do do whatever is needed.
    – Centimane
    Sep 9, 2016 at 16:11
  • @Centimane see Why not to parse ls?... Sep 9, 2016 at 16:17
7

You may find the symlinks utility useful:

$ symlinks -r .
other_fs: /home/chazelas/test/bin -> /bin
dangling: /home/chazelas/test/DIR/foo -> foo
dangling: /home/chazelas/test/blah -> not-here
absolute: /home/chazelas/test/chazelas -> /home/chazelas

And can fix the links for you. Here with -t to tell what it would do:

$ symlinks -rct .
other_fs: /home/chazelas/test/bin -> /bin
dangling: /home/chazelas/test/DIR/foo -> foo
dangling: /home/chazelas/test/blah -> not-here
absolute: /home/chazelas/test/chazelas -> /home/chazelas
changed:  /home/chazelas/test/chazelas -> ../../chazelas

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .